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ę” .
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:
7.2.13 Porównanie równości abstrakcyjnej
Porównaniex == y
, gdziex
iy
są wartościami, daje wartośćtrue
lubfalse
. Takie porównanie przeprowadza się w następujący sposób:
- Jeśli
Type(x)
jest taki sam jakType(y)
, to:
- za. Zwraca wynik wykonania porównania ścisłej równości
x === y
.
- Jeśli
x
jestnull
ay
jestundefined
, zwracatrue
.- Jeśli
x
jestundefined
ay
manull
, zwróćnull
true
.- Jeśli
Type(x)
toNumber
aType(y)
toString
, zwróć wynik porównaniax == ToNumber(y)
.- Jeśli
Type(x)
toString
aType(y)
toNumber
, zwróć wynik porównaniaToNumber(x) == y
.- Jeśli
Type(x)
jest wartościąBoolean
, zwróć wynik porównaniaToNumber(x) == y
.- Jeśli
Type(y)
jest wartościąBoolean
, zwróć wynikcomparison x == ToNumber(y)
.- Jeśli
Type(x)
toString
,Number
lubSymbol
aType(y)
toObject
, zwróć wynik porównaniax == ToPrimitive(y)
.- Jeśli
Type(x)
to Object, aType(y)
toString
,Number
lubSymbol
, zwróć wynik porównaniaToPrimitive(x) == y
.- 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żnaundefined
) -
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 cieniowanieArray
lubNumber
. - Unikaj ustawiania czegoś jako
undefined
. Jeśli chcesz usunąć pasek właściwości z obiektufoo
,delete foo.bar;
zamiast. - Identyfikator testowania istnienia
foo
przeciwkoundefined
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
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
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
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? .
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ścix
- Symetria :
Object.is(x, y)
jesttrue
, wtedy i tylko wtedy, gdyObject.is(y, x)
jesttrue
dla żadnej wartościx
iy
. - Przechodniość : Jeśli
Object.is(x, y)
iObject.is(y, z)
sątrue
, toObject.is(x, z)
jest równieżtrue
, dla dowolnych wartościx
,y
iz
.
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)
jesttrue
, dla dowolnej wartościx
- Symetria :
[x].includes(y)
jesttrue
jeśli tylko i tylko wtedy, gdy[y].includes(x)
jesttrue
, dla dowolnych wartościx
iy
. - Przechodniość : Jeśli
[x].includes(y)
i[y].includes(z)
jesttrue
, wówczas[x].includes(z)
również jesttrue
, dla dowolnych wartościx
,y
iz
.
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
jesttrue
wtedy i tylko wtedy, gdy y === xis
prawdziwe, for any values
xand
y`. - Przechodniość : Jeśli
x === y
iy === z
sątrue
, tox === z
jest równieżtrue
, dla dowolnych wartościx
,y
iz
.
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
inull
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
jesttrue
wtedy i tylko wtedy, gdyy == x
jesttrue
, dla wszelkich wartościx
iy
.
Ale nie jest relacją równoważności, ponieważ
-
NaN
nie jest zwrotny :NaN != NaN
- Przechodniość nie zachowuje się, np.
0 == ''
i0 == '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ć.