Szukaj…


Uwagi

Podczas używania koercji logicznej następujące wartości są uważane za „fałsz” :

  • false
  • 0
  • "" (pusty ciąg)
  • null
  • undefined
  • NaN (nie jest liczbą, np. 0/0 )
  • document.all ¹ (kontekst przeglądarki)

Cała reszta jest uważana za „prawdę” .

¹ celowe naruszenie specyfikacji ECMAScript

Operatory logiczne z logicznymi wartościami logicznymi

var x = true,
    y = false;

I

Ten operator zwróci true, jeśli oba wyrażenia będą miały wartość true. Ten operator boolowski zastosuje zwarcie i nie oceni y jeśli x wartość false .

x && y;

Zwróci to wartość false, ponieważ y jest false.

LUB

Ten operator zwróci true, jeśli jedno z dwóch wyrażeń ma wartość true. Ten operator logiczny zastosuje zwarcie i y nie zostanie ocenione, jeśli x będzie miało wartość true .

x || y;

Zwróci to wartość true, ponieważ x jest true.

NIE

Ten operator zwróci false, jeśli wyrażenie po prawej stronie ma wartość true, i zwróci true, jeśli wyrażenie po prawej stronie ma wartość false.

!x;

To zwróci false, ponieważ x jest prawdą.

Równość abstrakcyjna (==)

Operandy abstrakcyjnego operatora równości są porównywane po przekonwertowaniu na typ wspólny. Sposób konwersji jest oparty na specyfikacji operatora:

Specyfikacja operatora == :

7.2.13 Porównanie równości abstrakcyjnej

Porównanie x == y , gdzie x i y są wartościami, daje wartość true lub false . Takie porównanie przeprowadza się w następujący sposób:

  1. Jeśli Type(x) jest taki sam jak Type(y) , to:
  • za. Zwraca wynik wykonania porównania ścisłej równości x === y .
  1. Jeśli x jest null a y jest undefined , zwraca true .
  2. Jeśli x jest undefined a y ma null , zwróć null true .
  3. Jeśli Type(x) to Number a Type(y) to String , zwróć wynik porównania x == ToNumber(y) .
  4. Jeśli Type(x) to String a Type(y) to Number , zwróć wynik porównania ToNumber(x) == y .
  5. Jeśli Type(x) jest wartością Boolean , zwróć wynik porównania ToNumber(x) == y .
  6. Jeśli Type(y) jest wartością Boolean , zwróć wynik comparison x == ToNumber(y) .
  7. Jeśli Type(x) to String , Number lub Symbol a Type(y) to Object , zwróć wynik porównania x == ToPrimitive(y) .
  8. Jeśli Type(x) to Object, a Type(y) to String , Number lub Symbol , zwróć wynik porównania ToPrimitive(x) == y .
  9. Zwróć false .

Przykłady:

1 == 1;                     // true
1 == true;                  // true  (operand converted to number: true => 1)
1 == '1';                   // true  (operand converted to number: '1' => 1 )
1 == '1.00';                // true
1 == '1.00000000001';       // false
1 == '1.00000000000000001'; // true  (true due to precision loss)
null == undefined;          // true  (spec #2)
1 == 2;                     // false
0 == false;                 // true
0 == undefined;             // false
0 == "";                    // true

Operatory relacyjne (<, <=,>,> =)

Gdy oba operandy są numeryczne, są one porównywane normalnie:

1 < 2        // true
2 <= 2       // true
3 >= 5       // false
true < false // false (implicitly converted to numbers, 1 > 0)

Gdy oba operandy są ciągami, są one porównywane leksykograficznie (zgodnie z kolejnością alfabetyczną):

'a' < 'b'    // true
'1' < '2'    // true
'100' > '12' // false ('100' is less than '12' lexicographically!)

Gdy jeden operand jest ciągiem, a drugi jest liczbą, ciąg jest konwertowany na liczbę przed porównaniem:

'1' < 2      // true
'3' > 2      // true
true > '2'   // false (true implicitly converted to number, 1 < 2)

Gdy ciąg nie jest numeryczny, konwersja numeryczna zwraca NaN (nie-liczbę). Porównywanie z NaN zawsze zwraca false :

1 < 'abc'    // false
1 > 'abc'    // false

Należy jednak zachować ostrożność przy porównywaniu wartości liczbowej z ciągami null , undefined lub pustymi:

1 > ''        // true
1 < ''        // false
1 > null      // true
1 < null      // false
1 > undefined // false
1 < undefined // false

Gdy jeden operand jest obiektem, a drugi jest liczbą, obiekt jest porównywany do liczby przed porównaniem, więc null jest szczególnym przypadkiem, ponieważ Number(null);//0

new Date(2015)< 1479480185280            // true
null > -1                                //true
({toString:function(){return 123}}) > 122  //true

Nierówność

Operator != Jest odwrotnością operatora == .
Zwróci wartość true jeśli argumenty nie będą równe.
Silnik javascript spróbuje przekonwertować oba operandy na pasujące typy, jeśli nie są tego samego typu. Uwaga: jeśli dwa operandy mają różne wewnętrzne odwołania w pamięci, wówczas zwracane będą wartości false .

Próba:

1 != '1'     // false
1 != 2       // true

W powyższej próbce 1 != '1' jest false ponieważ typ liczby pierwotnej jest porównywany z wartością char . Dlatego silnik Javascript nie dba o typ danych wartości RHS.

Operator !== jest odwrotnością operatora === . Zwróci true, jeśli argumenty nie są równe lub jeśli ich typy nie są zgodne.

Przykład:

1 !== '1'    // true
1 !== 2      // true
1 !== 1      // false

Operatory logiczne o wartościach innych niż boolowskie (koercja boolowska)

Logiczne OR ( || ), czytanie od lewej do prawej, oceni do pierwszej prawdziwej wartości. Jeśli nie zostanie znaleziona żadna prawdziwa wartość, zwracana jest ostatnia wartość.

var a = 'hello' || '';             // a = 'hello'
var b = '' || [];                  // b = []
var c = '' || undefined;           // c = undefined
var d = 1 || 5;                    // d = 1
var e = 0 || {};                   // e = {}
var f = 0 || '' || 5;              // f = 5
var g = '' || 'yay' || 'boo';      // g = 'yay'

Logiczne ORAZ ( && ), czytanie od lewej do prawej, oceni pierwszą wartość falsy . Jeśli nie znaleziono wartości falsey, zwracana jest ostatnia wartość.

var a = 'hello' && '';                  // a = ''
var b = '' && [];                       // b = ''
var c = undefined && 0;                 // c = undefined
var d = 1 && 5;                         // d = 5
var e = 0 && {};                        // e = 0
var f = 'hi' && [] && 'done';           // f = 'done'
var g = 'bye' && undefined && 'adios';  // g = undefined

Tej sztuczki można na przykład użyć do ustawienia domyślnej wartości argumentu funkcji (przed ES6).

var foo = function(val) {
    // if val evaluates to falsey, 'default' will be returned instead.
    return val || 'default';
}

console.log( foo('burger') );  // burger
console.log( foo(100) );       // 100
console.log( foo([]) );        // []
console.log( foo(0) );         // default
console.log( foo(undefined) ); // default

Pamiętaj tylko, że w przypadku argumentów 0 i (w mniejszym stopniu) pusty ciąg są również często prawidłowymi wartościami, które powinny być w stanie jawnie przekazać i zastąpić wartość domyślną, co przy tym wzorcu nie będzie (ponieważ są falsy ).

Null and Undefined

Różnice między null a undefined

null i undefined wspólna równość abstrakcyjna == ale nie ścisła równość === ,

null == undefined   // true
null === undefined  // false

Reprezentują nieco inne rzeczy:

  • undefined reprezentuje brak wartości , na przykład przed utworzeniem właściwości identyfikatora / obiektu lub w okresie między utworzeniem identyfikatora / parametru funkcji a jego pierwszym ustawieniem, jeśli istnieje.
  • null oznacza celowy brak wartości identyfikatora lub właściwości, które zostały już utworzone.

Są to różne typy składni:

  • undefined jest własnością globalnego obiektu , zwykle niezmienną w zasięgu globalnym. Oznacza to, że w dowolnym miejscu, w którym można zdefiniować identyfikator inny niż w globalnej przestrzeni nazw, można ukryć undefined przed tym zakresem (chociaż rzeczy wciąż można undefined )
  • null to dosłowne słowo , więc jego znaczenia nigdy nie można zmienić, a próba zrobienia tego spowoduje błąd .

Podobieństwa między null a undefined

null i undefined są fałszem.

if (null) console.log("won't be logged");
if (undefined) console.log("won't be logged");

Ani null ani undefined równa się false (patrz to pytanie ).

false == undefined   // false
false == null        // false
false === undefined  // false
false === null       // false

Używanie undefined

  • Jeśli bieżący zakres nie może być zaufany, użyj czegoś, co daje wartość niezdefiniowaną , na przykład void 0; .
  • Jeśli undefined jest cień innej wartości, jest tak samo zła jak cieniowanie Array lub Number .
  • Unikaj ustawiania czegoś jako undefined . Jeśli chcesz usunąć pasek właściwości z obiektu foo , delete foo.bar; zamiast.
  • Identyfikator testowania istnienia foo przeciwko undefined może zgłosić błąd odniesienia , zamiast tego należy użyć typeof foo przeciwko "undefined" .

Właściwość NaN obiektu globalnego

NaN („ N no a N umber”) to specjalna wartość zdefiniowana w standardzie IEEE dla arytmetyki zmiennoprzecinkowej , która jest używana, gdy podano wartość nienumeryczną, ale spodziewana jest liczba ( 1 * "two" ), lub gdy obliczenie nie posiada ważnego number wyniku ( Math.sqrt(-1) ).

Wszelkie porównania równości lub relacji z NaN zwracają false , nawet porównując je ze sobą. Ponieważ NaN ma oznaczać wynik bezsensownego obliczenia i jako taki nie jest równy wynikowi innych bezsensownych obliczeń.

(1 * "two") === NaN  //false

NaN === 0;          // false
NaN === NaN;        // false
Number.NaN === NaN; // false

NaN < 0;            // false
NaN > 0;            // false
NaN > 0;            // false
NaN >= NaN;         // false
NaN >= 'two';       // false

Nierówne porównania zawsze zwracają wartość true :

NaN !== 0;          // true
NaN !== NaN;        // true

Sprawdzanie, czy wartością jest NaN

6

Możesz przetestować wartość lub wyrażenie dla NaN za pomocą funkcji Number.isNaN () :

Number.isNaN(NaN);         // true
Number.isNaN(0 / 0);       // true
Number.isNaN('str' - 12);  // true

Number.isNaN(24);          // false
Number.isNaN('24');        // false
Number.isNaN(1 / 0);       // false
Number.isNaN(Infinity);    // false

Number.isNaN('str');       // false
Number.isNaN(undefined);   // false
Number.isNaN({});          // false
6

Możesz sprawdzić, czy wartość jest NaN , porównując ją z samym sobą:

value !== value;    // true for NaN, false for any other value

Do Number.isNaN() można użyć następującego wypełnienia:

Number.isNaN = Number.isNaN || function(value) {     
    return value !== value;
}

Z kolei funkcja globalna isNaN() zwraca wartość true nie tylko dla NaN , ale także dla dowolnej wartości lub wyrażenia, które nie mogą zostać przekonwertowane na liczbę:

isNaN(NaN);         // true
isNaN(0 / 0);       // true
isNaN('str' - 12);  // true

isNaN(24);          // false
isNaN('24');        // false
isNaN(Infinity);    // false

isNaN('str');       // true
isNaN(undefined);   // true
isNaN({});          // true

ECMAScript definiuje algorytm „identyczności” o nazwie SameValue który od ECMAScript 6 można wywoływać za pomocą Object.is . W przeciwieństwie do porównania == i === , użycie Object.is() będzie traktować NaN jako identyczne z samym sobą (i -0 jako nie identyczne z +0 ):

Object.is(NaN, NaN)      // true
Object.is(+0, 0)         // false

NaN === NaN              // false
+0 === 0                 // true
6

Do Object.is() (z MDN ) możesz użyć następującego wypełnienia:

if (!Object.is) {
  Object.is = function(x, y) {
    // SameValue algorithm
    if (x === y) { // Steps 1-5, 7-10
      // Steps 6.b-6.e: +0 != -0
      return x !== 0 || 1 / x === 1 / y;
    } else {
      // Step 6.a: NaN == NaN
      return x !== x && y !== y;
    }
  };
}

Punkty do odnotowania

Sam NaN jest liczbą, co oznacza, że nie jest równy ciągowi „NaN”, a co najważniejsze (choć być może nieinicjatywne):

typeof(NaN) === "number"; //true

Zwarcie u operatorów logicznych

Operator i ( && ) i operator lub ( || ) stosują zwarcie, aby zapobiec niepotrzebnej pracy, jeśli wynik operacji nie zmieni się wraz z dodatkową pracą.

W x && y y nie będzie oceniane, jeśli x wartość false , ponieważ całe wyrażenie ma gwarancję false .

In x || y , y nie zostanie ocenione, jeśli x ocenione na true , ponieważ gwarantujemy, że całe wyrażenie będzie true .

Przykład z funkcjami

Weź następujące dwie funkcje:

function T() { // True
  console.log("T");
  return true;
}

function F() { // False
  console.log("F");
  return false;
}

Przykład 1

T() && F(); // false

Wynik:

„T”
'FA'

Przykład 2

F() && T(); // false

Wynik:

'FA'

Przykład 3

T() || F(); // true

Wynik:

„T”

Przykład 4

F() || T(); // true

Wynik:

'FA'
„T”


Zwarcie w celu uniknięcia błędów

var obj; // object has value of undefined
if(obj.property){ }// TypeError: Cannot read property 'property' of undefined
if(obj.property && obj !== undefined){}// Line A TypeError: Cannot read property 'property' of undefined

Wiersz A: jeśli odwrócisz kolejność, pierwsza instrukcja warunkowa zapobiegnie błędowi w drugiej, nie wykonując go, jeśli spowodowałby błąd

if(obj !== undefined && obj.property){}; // no error thrown 

Ale należy go używać tylko wtedy, gdy oczekujesz undefined

if(typeof obj === "object" && obj.property){}; // safe option but slower

Zwarcie w celu zapewnienia wartości domyślnej

|| Za pomocą operatora można wybrać wartość „prawdomówną” lub wartość domyślną.

Na przykład można tego użyć, aby przekonwertować wartość dopuszczającą wartość null na wartość niedozwoloną:

var nullableObj = null;
var obj = nullableObj || {};  // this selects {}

var nullableObj2 = {x: 5};
var obj2 = nullableObj2 || {} // this selects {x: 5}

Lub zwrócić pierwszą prawdziwą wartość

var truthyValue = {x: 10};
return truthyValue || {}; // will return {x: 10}

To samo można wykorzystać do wielokrotnego cofnięcia się:

envVariable || configValue || defaultConstValue // select the first "truthy" of these

Zwarcie w celu wywołania funkcji opcjonalnej

Za pomocą operatora && można ocenić połączenie zwrotne, tylko jeśli zostanie ono przekazane:

function myMethod(cb) {
    // This can be simplified
    if (cb) {
       cb();
    }

    // To this
    cb && cb();
}

Oczywiście powyższy test nie potwierdza, że cb jest w rzeczywistości function a nie tylko Object / Array / String / Number .

Streszczenie równości / nierówności i konwersji typu

Problem

Abstrakcyjne operatory równości i nierówności ( == i != ) Konwertują swoje argumenty, jeśli typy argumentów nie są zgodne. Ten rodzaj przymusu jest powszechnym źródłem nieporozumień na temat wyników tych operatorów, w szczególności operatory te nie zawsze są przechodnie, jak można by się spodziewać.

"" ==  0;     // true A
 0 == "0";    // true A
"" == "0";    // false B
false == 0;   // true
false == "0"; // true

"" !=  0;     // false A
 0 != "0";    // false A
"" != "0";    // true B
false != 0;   // false
false != "0"; // false

Wyniki zaczynają mieć sens, jeśli weźmiesz pod uwagę sposób, w jaki JavaScript konwertuje puste ciągi na liczby.

Number("");    // 0
Number("0");   // 0
Number(false); // 0

Rozwiązanie

W instrukcji false B oba operandy są łańcuchami ( "" i "0" ), stąd konwersja typu nie będzie możliwa, a ponieważ "" i "0" nie są tej samej wartości, "" == "0" jest false zgodnie z oczekiwaniami.

Jednym ze sposobów na wyeliminowanie nieoczekiwanego zachowania jest upewnienie się, że zawsze porównujesz operandy tego samego typu. Na przykład, jeśli chcesz wyniki porównania numerycznego, użyj jawnej konwersji:

var test = (a,b) => Number(a) == Number(b); 
test("", 0);        // true;
test("0", 0);       // true
test("", "0");      // true;
test("abc", "abc"); // false as operands are not numbers 

Lub jeśli chcesz porównać ciąg znaków:

var test = (a,b) => String(a) == String(b);
test("", 0);   // false;
test("0", 0);  // true
test("", "0"); // false;

Uwaga dodatkowa : Number("0") i new Number("0") to nie to samo! Podczas gdy pierwszy wykonuje konwersję typu, drugi tworzy nowy obiekt. Obiekty są porównywane przez odniesienie, a nie według wartości, co wyjaśnia poniższe wyniki.

Number("0") == Number("0");         // true;
new Number("0") == new Number("0"); // false 

Wreszcie masz opcję użycia ścisłych operatorów równości i nierówności, które nie będą wykonywać żadnych domyślnych konwersji typu.

"" ===  0;  // false
 0 === "0"; // false
"" === "0"; // false

Dalsze odniesienia do tego tematu można znaleźć tutaj:

Który operator równości (== vs ===) powinien być używany w porównaniach JavaScript? .

Równość abstrakcyjna (==)

Pusta tablica

/* ToNumber(ToPrimitive([])) == ToNumber(false) */
[] == false; // true

Po wykonaniu [].toString() wywołuje [].join() jeśli istnieje, lub w przeciwnym wypadku Object.prototype.toString() . To porównanie zwraca wartość true ponieważ [].join() zwraca '' co po wymuszeniu na 0 jest równe false ToNumber .

Uważaj jednak, wszystkie obiekty są prawdziwe, a Array jest instancją Object :

// Internally this is evaluated as ToBoolean([]) === true ? 'truthy' : 'falsy'
[] ? 'truthy' : 'falsy'; // 'truthy'

Operacje porównywania równości

JavaScript ma cztery różne operacje porównywania równości.

SameValue

Zwraca true jeśli oba operandy należą do tego samego typu i mają tę samą wartość.

Uwaga: wartość obiektu jest referencją.

Możesz użyć tego algorytmu porównania za pośrednictwem Object.is (ECMAScript 6).

Przykłady:

Object.is(1, 1);            // true
Object.is(+0, -0);          // false
Object.is(NaN, NaN);        // true
Object.is(true, "true");    // false
Object.is(false, 0);        // false
Object.is(null, undefined); // false
Object.is(1, "1");          // false
Object.is([], []);          // false

Ten algorytm ma właściwości relacji równoważności :

  • Refleksyjność : Object.is(x, x) ma wartość true dla dowolnej wartości x
  • Symetria : Object.is(x, y) jest true , wtedy i tylko wtedy, gdy Object.is(y, x) jest true dla żadnej wartości x i y .
  • Przechodniość : Jeśli Object.is(x, y) i Object.is(y, z)true , to Object.is(x, z) jest również true , dla dowolnych wartości x , y i z .

SameValueZero

Zachowuje się jak SameValue, ale uważa, że +0 i -0 są równe.

Tego algorytmu porównania można użyć za pośrednictwem Array.prototype.includes (ECMAScript 7).

Przykłady:

[1].includes(1);            // true
[+0].includes(-0);          // true
[NaN].includes(NaN);        // true
[true].includes("true");    // false
[false].includes(0);        // false
[1].includes("1");          // false
[null].includes(undefined); // false
[[]].includes([]);          // false

Ten algorytm nadal ma właściwości relacji równoważności :

  • Zwrotność : [x].includes(x) jest true , dla dowolnej wartości x
  • Symetria : [x].includes(y) jest true jeśli tylko i tylko wtedy, gdy [y].includes(x) jest true , dla dowolnych wartości x i y .
  • Przechodniość : Jeśli [x].includes(y) i [y].includes(z) jest true , wówczas [x].includes(z) również jest true , dla dowolnych wartości x , y i z .

Porównanie ścisłej równości

Zachowuje się jak SameValue, ale

  • Uważa, że +0 i -0 są równe.
  • Uważa, że NaN inny niż jakakolwiek wartość, w tym sama

Możesz użyć tego algorytmu porównania za pomocą operatora === (ECMAScript 3).

Istnieje również operator !== (ECMAScript 3), który neguje wynik === .

Przykłady:

1 === 1;            // true
+0 === -0;          // true
NaN === NaN;        // false
true === "true";    // false
false === 0;        // false
1 === "1";          // false
null === undefined; // false
[] === [];          // false

Ten algorytm ma następujące właściwości:

  • Symetria : x === y jest true wtedy i tylko wtedy, gdy y === x is prawdziwe , for any values x and y`.
  • Przechodniość : Jeśli x === y i y === ztrue , to x === z jest również true , dla dowolnych wartości x , y i z .

Ale nie jest relacją równoważności, ponieważ

  • NaN nie jest zwrotny : NaN !== NaN

Porównanie równości abstrakcyjnej

Jeśli oba operandy należą do tego samego typu, zachowuje się jak porównanie ścisłej równości.

W przeciwnym razie wymusza je w następujący sposób:

  • undefined i null są uważane za równe
  • Podczas porównywania liczby z ciągiem łańcuch jest wymuszany na liczbę
  • Porównując wartość logiczną z czymś innym, wartość logiczna jest wymuszana na liczbę
  • Porównując obiekt z liczbą, łańcuchem lub symbolem, obiekt jest zmuszany do operacji podstawowej

Jeśli był przymus, wartości wymuszone są porównywane rekurencyjnie. W przeciwnym razie algorytm zwraca wartość false .

Możesz użyć tego algorytmu porównania za pomocą operatora == (ECMAScript 1).

Istnieje również operator != (ECMAScript 1), który neguje wynik == .

Przykłady:

1 == 1;            // true
+0 == -0;          // true
NaN == NaN;        // false
true == "true";    // false
false == 0;        // true
1 == "1";          // true
null == undefined; // true
[] == [];          // false

Ten algorytm ma następującą właściwość:

  • Symetria : x == y jest true wtedy i tylko wtedy, gdy y == x jest true , dla wszelkich wartości x i y .

Ale nie jest relacją równoważności, ponieważ

  • NaN nie jest zwrotny : NaN != NaN
  • Przechodniość nie zachowuje się, np. 0 == '' i 0 == '0' , ale '' != '0'

Grupowanie wielu instrukcji logicznych

Możesz pogrupować wiele nawiasów logicznych w nawiasach, aby stworzyć bardziej złożoną ocenę logiczną, szczególnie przydatną w instrukcjach if.

if ((age >= 18 && height >= 5.11) || (status === 'royalty' && hasInvitation)) {
  console.log('You can enter our club');
}

Możemy również przenieść zgrupowaną logikę do zmiennych, aby instrukcja była nieco krótsza i opisowa:

var isLegal = age >= 18;
var tall = height >= 5.11;
var suitable = isLegal && tall;
var isRoyalty = status === 'royalty';
var specialCase = isRoyalty && hasInvitation;
var canEnterOurBar = suitable || specialCase;

if (canEnterOurBar) console.log('You can enter our club');

Zauważ, że w tym konkretnym przykładzie (i wielu innych) grupowanie instrukcji w nawiasach działa tak samo, jakbyśmy je usunęli, po prostu wykonaj liniową ocenę logiczną, a znajdziesz się z tym samym rezultatem. Wolę używać nawiasów, ponieważ pozwala mi to lepiej zrozumieć, co zamierzałem, i może zapobiec błędom logicznym.

Automatyczne konwersje typów

Uwaga: liczby można przypadkowo przekonwertować na ciągi znaków lub NaN (nie liczbę).

JavaScript jest luźno wpisany. Zmienna może zawierać różne typy danych, a zmienna może zmieniać typ danych:

var x = "Hello";     // typeof x is a string
x = 5;               // changes typeof x to a number

Podczas wykonywania operacji matematycznych JavaScript może konwertować liczby na ciągi:

var x = 5 + 7;       // x.valueOf() is 12,  typeof x is a number
var x = 5 + "7";     // x.valueOf() is 57,  typeof x is a string
var x = "5" + 7;     // x.valueOf() is 57,  typeof x is a string
var x = 5 - 7;       // x.valueOf() is -2,  typeof x is a number
var x = 5 - "7";     // x.valueOf() is -2,  typeof x is a number
var x = "5" - 7;     // x.valueOf() is -2,  typeof x is a number
var x = 5 - "x";     // x.valueOf() is NaN, typeof x is a number

Odejmowanie ciągu od ciągu nie generuje błędu, ale zwraca NaN (nie liczbę):

"Hello" - "Dolly"    // returns NaN

Lista operatorów porównania

Operator Porównanie Przykład
== Równy i == 0
=== Równa wartość i rodzaj i === "5"
!= Nie równe i != 5
!== Nie równa wartość lub typ i !== 5
> Lepszy niż i > 5
< Mniej niż i < 5
>= Większy bądź równy i >= 5
<= Mniejszy lub równy i <= 5

Pola bitowe w celu optymalizacji porównania danych o wielu stanach

Pole bitowe jest zmienną, która przechowuje różne stany logiczne jako pojedyncze bity. Trochę włączony byłby prawdziwy, a wyłączony byłby fałszywy. W przeszłości pola bitowe były rutynowo używane, ponieważ oszczędzały pamięć i zmniejszały obciążenie przetwarzania. Chociaż potrzeba użycia pola bitowego nie jest już tak ważna, oferują pewne korzyści, które mogą uprościć wiele zadań przetwarzania.

Na przykład dane wprowadzone przez użytkownika. Gdy pobierasz dane z klawiszy kierunkowych w górę, w dół, w lewo, w prawo, możesz zakodować różne klawisze w jedną zmienną z przypisanym bitem dla każdego kierunku.

Przykład czytania klawiatury przez bitfield

var bitField = 0;  // the value to hold the bits
const KEY_BITS = [4,1,8,2]; // left up right down
const KEY_MASKS = [0b1011,0b1110,0b0111,0b1101]; // left up right down
window.onkeydown = window.onkeyup = function (e) {
    if(e.keyCode >= 37 && e.keyCode <41){
        if(e.type === "keydown"){
            bitField |= KEY_BITS[e.keyCode - 37];
        }else{
            bitField &= KEY_MASKS[e.keyCode - 37];
        }
    }    
}

Przykład czytania w postaci tablicy

var directionState = [false,false,false,false];
window.onkeydown = window.onkeyup = function (e) {
    if(e.keyCode >= 37 && e.keyCode <41){
        directionState[e.keyCode - 37] = e.type === "keydown";
    }    
}

Aby włączyć nieco, użyj bitowego lub | i wartość odpowiadającą bitowi. Więc jeśli chcesz ustawić drugi bit bitField |= 0b10 włączy go. Jeśli chcesz trochę wyłączyć, użyj bitowego i & z wartością, która ma wszystkie wymagane bity. Użycie 4 bitów i wyłączenie drugiego bitu w bitfield &= 0b1101;

Można powiedzieć, że powyższy przykład wydaje się o wiele bardziej złożony niż przypisywanie różnych stanów kluczy do tablicy. Tak Ustawienie jest nieco bardziej skomplikowane, ale zaletą jest przesłuchanie stanu.

Jeśli chcesz sprawdzić, czy wszystkie klucze są uruchomione.

// as bit field
if(!bitfield) // no keys are on

// as array test each item in array
if(!(directionState[0] && directionState[1] && directionState[2] && directionState[3])){

Możesz ustawić niektóre stałe, aby ułatwić

// postfix U,D,L,R for Up down left right
const KEY_U = 1;
const KEY_D = 2;
const KEY_L = 4;
const KEY_R = 8;
const KEY_UL = KEY_U + KEY_L; // up left
const KEY_UR = KEY_U + KEY_R; // up Right
const KEY_DL = KEY_D + KEY_L; // down left
const KEY_DR = KEY_D + KEY_R; // down right

Następnie możesz szybko przetestować wiele różnych stanów klawiatury

if ((bitfield & KEY_UL) === KEY_UL) { // is UP and LEFT only down
if (bitfield  & KEY_UL) {             // is Up left down 
if ((bitfield & KEY_U) === KEY_U) {   // is Up only down
if (bitfield & KEY_U) {               // is Up down (any other key may be down)
if (!(bitfield & KEY_U)) {            // is Up up (any other key may be down)
if (!bitfield ) {                     // no keys are down
if (bitfield ) {                      // any one or more keys are down

Klawiatura jest tylko jednym przykładem. Pola bitowe są przydatne, gdy masz różne stany, w których należy działać łącznie. JavaScript może używać do 32 bitów dla pola bitowego. Korzystanie z nich może zapewnić znaczny wzrost wydajności. Warto się z nimi zapoznać.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow