Ricerca…
Osservazioni
Quando si usa la coercizione booleana, i seguenti valori sono considerati "falsi" :
-
false
-
0
-
""
(stringa vuota) -
null
-
undefined
-
NaN
(non un numero, ad esempio0/0
) -
document.all
¹ (contesto del browser)
Tutto il resto è considerato "vero" .
Operatori di logica con booleani
var x = true,
y = false;
E
Questo operatore restituirà true se entrambe le espressioni valgono come true. Questo operatore booleano utilizzerà il cortocircuito e non valuterà y
se x
restituisce false
.
x && y;
Questo restituirà false, perché y
è falso.
O
Questo operatore restituirà true se una delle due espressioni è true. Questo operatore booleano impiegherà il cortocircuito e y
non sarà valutato se x
true
.
x || y;
Questo restituirà true, perché x
è vero.
NON
Questo operatore restituirà false se l'espressione a destra restituisce true e restituisce true se l'espressione a destra restituisce false.
!x;
Questo restituirà false, perché x
è vero.
Equality astratta (==)
Gli operatori dell'operatore di uguaglianza astratta vengono confrontati dopo essere stati convertiti in un tipo comune. Come avviene questa conversione si basa sulle specifiche dell'operatore:
Specifica per l'operatore ==
:
7.2.13 Paragone di uguaglianza astratta
Il confrontox == y
, dovex
edy
sono valori, producetrue
ofalse
. Tale confronto viene eseguito come segue:
- Se
Type(x)
è uguale aType(y)
, allora:
- un. Restituisce il risultato dell'esecuzione del Confronto di uguaglianza rigorosa
x === y
.
- Se
x
ènull
ey
undefined
èundefined
, restituiscetrue
.- Se
x
undefined
èundefined
ey
ènull
, restituiscetrue
.- Se
Type(x)
èNumber
eType(y)
èString
, restituisce il risultato del confrontox == ToNumber(y)
.- Se
Type(x)
èString
eType(y)
èNumber
, restituisce il risultato del confrontoToNumber(x) == y
.- Se
Type(x)
èBoolean
, restituisce il risultato del confrontoToNumber(x) == y
.- Se
Type(y)
èBoolean
, restituisce il risultato delcomparison x == ToNumber(y)
.- Se
Type(x)
èString
,Number
oSymbol
eType(y)
èObject
, restituisce il risultato del confrontox == ToPrimitive(y)
.- Se
Type(x)
è Object eType(y)
èString
,Number
oSymbol
, restituisce il risultato del confrontoToPrimitive(x) == y
.- Restituire
false
.
Esempi:
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
Operatori relazionali (<, <=,>,> =)
Quando entrambi gli operandi sono numerici, vengono confrontati normalmente:
1 < 2 // true
2 <= 2 // true
3 >= 5 // false
true < false // false (implicitly converted to numbers, 1 > 0)
Quando entrambi gli operandi sono stringhe, vengono confrontati lessicograficamente (secondo l'ordine alfabetico):
'a' < 'b' // true
'1' < '2' // true
'100' > '12' // false ('100' is less than '12' lexicographically!)
Quando un operando è una stringa e l'altro è un numero, la stringa viene convertita in un numero prima del confronto:
'1' < 2 // true
'3' > 2 // true
true > '2' // false (true implicitly converted to number, 1 < 2)
Quando la stringa non è numerica, la conversione numerica restituisce NaN
(non-un-numero). Il confronto con NaN
restituisce sempre false
:
1 < 'abc' // false
1 > 'abc' // false
Ma attenzione quando si confronta un valore numerico con null
, undefined
o stringhe vuote:
1 > '' // true
1 < '' // false
1 > null // true
1 < null // false
1 > undefined // false
1 < undefined // false
Quando un operando è un oggetto e l'altro è un numero, l'oggetto viene convertito in un numero prima del confronto. null
è caso particolare perché Number(null);//0
new Date(2015)< 1479480185280 // true
null > -1 //true
({toString:function(){return 123}}) > 122 //true
Disuguaglianza
Operatore !=
È l'inverso dell'operatore ==
.
Restituisce true
se gli operandi non sono uguali.
Il motore javascript proverà a convertire entrambi gli operandi in tipi corrispondenti se non sono dello stesso tipo. Nota: se i due operandi hanno riferimenti interni diversi in memoria, verrà restituito false
.
Campione:
1 != '1' // false
1 != 2 // true
Nell'esempio sopra, 1 != '1'
è false
perché, un tipo di numero primitivo viene confrontato con un valore char
. Pertanto, il motore Javascript non si preoccupa del tipo di dati del valore RHS.
Operatore !==
è l'inverso dell'operatore ===
. Restituisce true se gli operandi non sono uguali o se i loro tipi non corrispondono.
Esempio:
1 !== '1' // true
1 !== 2 // true
1 !== 1 // false
Operatori di logica con valori non booleani (coercizione booleana)
L'OR logico ( ||
), letto da sinistra a destra, valuterà il primo valore di verità . Se non viene trovato alcun valore di verità , viene restituito l'ultimo valore.
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'
L'AND logico ( &&
), letto da sinistra a destra, valuterà il primo valore di falsy . Se non viene trovato alcun valore falso , viene restituito l'ultimo valore.
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
Questo trucco può essere utilizzato, ad esempio, per impostare un valore predefinito per un argomento di funzione (prima di 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
Tieni a mente che per gli argomenti, 0
e (in misura minore) la stringa vuota sono anche spesso valori validi che dovrebbero poter essere esplicitamente passati e sovrascrivere un valore predefinito, che, con questo modello, non lo faranno (perché sono falsi ).
Nullo e indefinito
Le differenze tra null
e undefined
null
e undefined
condividi l'uguaglianza astratta ==
ma non l'uguaglianza rigorosa ===
,
null == undefined // true
null === undefined // false
Rappresentano cose leggermente diverse:
-
undefined
rappresenta l' assenza di un valore , come prima che sia stata creata una proprietà identificatore / oggetto o nel periodo tra la creazione del parametro identificatore / funzione e il primo set, se presente. -
null
rappresenta l' assenza intenzionale di un valore per un identificatore o una proprietà che è già stata creata.
Sono diversi tipi di sintassi:
-
undefined
è una proprietà dell'oggetto globale , solitamente immutabile nell'ambito globale. Ciò significa che ovunque è possibile definire un identificatore diverso da quello nello spazio dei nomi globale potrebbe nascondersiundefined
da tale ambito (anche se le cose possono ancora essereundefined
) -
null
è una parola letterale , quindi il suo significato non può mai essere cambiato e il tentativo di farlo genererà un errore .
Le somiglianze tra null
e undefined
null
e undefined
sono entrambi falsi.
if (null) console.log("won't be logged");
if (undefined) console.log("won't be logged");
Né null
né undefined
uguale a false
(vedi questa domanda ).
false == undefined // false
false == null // false
false === undefined // false
false === null // false
Uso undefined
- Se non è possibile attendersi l'ambito corrente, utilizzare qualcosa che non è definito , ad esempio
void 0;
. - Se
undefined
è ombreggiato da un altro valore, è altrettanto brutto quanto lo shadowingArray
oNumber
. - Evita di impostare qualcosa di
undefined
. Se si desidera rimuovere una barra delle proprietà da un oggettofoo
,delete foo.bar;
anziché. - L'identificatore di test dell'esistenza
foo
controundefined
potrebbe generare un errore di riferimento , utilizzare invecetypeof foo
contro"undefined"
.
Proprietà NaN dell'oggetto globale
NaN
(" N ot a N umber") è un valore speciale definito dallo standard IEEE per l'aritmetica virgola mobile , che viene utilizzato quando viene fornito un valore non numerico, ma un numero è previsto ( 1 * "two"
) o quando un calcolo non ha un risultato number
valido ( Math.sqrt(-1)
).
Qualsiasi paragone di uguaglianza o di relazione con NaN
restituisce un valore false
, anche confrontandolo con se stesso. Perché, si suppone che NaN
denoti il risultato di un calcolo insensato e, in quanto tale, non è uguale al risultato di altri calcoli privi di senso.
(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
I confronti non uguali restituiranno sempre true
:
NaN !== 0; // true
NaN !== NaN; // true
Verifica se un valore è NaN
È possibile testare un valore o un'espressione per NaN
utilizzando la funzione 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
Puoi verificare se un valore è NaN
confrontandolo con se stesso:
value !== value; // true for NaN, false for any other value
È possibile utilizzare il seguente polyfill per Number.isNaN()
:
Number.isNaN = Number.isNaN || function(value) {
return value !== value;
}
Al contrario, la funzione globale isNaN()
restituisce true
non solo per NaN
, ma anche per qualsiasi valore o espressione che non può essere forzato in un numero:
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 definisce un algoritmo di "uguaglianza" chiamato SameValue
che, dal momento che ECMAScript 6, può essere richiamato con Object.is
. A differenza del confronto ==
e ===
, l'uso di Object.is()
considera NaN
identico a se stesso (e -0
come non identico a +0
):
Object.is(NaN, NaN) // true
Object.is(+0, 0) // false
NaN === NaN // false
+0 === 0 // true
È possibile utilizzare il seguente polyfill per Object.is()
(da MDN ):
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;
}
};
}
Punti da notare
NaN stesso è un numero, il che significa che non è uguale alla stringa "NaN" e, cosa più importante (anche se forse non intuitivamente):
typeof(NaN) === "number"; //true
Cortocircuito negli operatori booleani
L'operatore e ( &&
) e l'operatore o ( ||
) impiegano il cortocircuito per evitare il lavoro non necessario se il risultato dell'operazione non cambia con il lavoro extra.
In x && y
, y
non verrà valutato se x
restituisce false
, poiché l'intera espressione è false
.
In x || y
, y
non verrà valutato se x
valutato su true
, poiché l'intera espressione è garantita come true
.
Esempio con funzioni
Prendi le seguenti due funzioni:
function T() { // True
console.log("T");
return true;
}
function F() { // False
console.log("F");
return false;
}
Esempio 1
T() && F(); // false
Produzione:
'T'
'F'
Esempio 2
F() && T(); // false
Produzione:
'F'
Esempio 3
T() || F(); // true
Produzione:
'T'
Esempio 4
F() || T(); // true
Produzione:
'F'
'T'
Cortocircuito per evitare errori
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
Linea A: se si inverte l'ordine, la prima istruzione condizionale impedirà l'errore sul secondo non eseguendolo se genererebbe l'errore
if(obj !== undefined && obj.property){}; // no error thrown
Ma dovrebbe essere usato solo se ti aspetti undefined
if(typeof obj === "object" && obj.property){}; // safe option but slower
Cortocircuito per fornire un valore predefinito
||
l'operatore può essere utilizzato per selezionare un valore "vero" o il valore predefinito.
Ad esempio, questo può essere usato per assicurare che un valore nullable sia convertito in un valore non annullabile:
var nullableObj = null;
var obj = nullableObj || {}; // this selects {}
var nullableObj2 = {x: 5};
var obj2 = nullableObj2 || {} // this selects {x: 5}
O per restituire il primo valore di verità
var truthyValue = {x: 10};
return truthyValue || {}; // will return {x: 10}
Lo stesso può essere usato per ripiegare più volte:
envVariable || configValue || defaultConstValue // select the first "truthy" of these
Cortocircuito per chiamare una funzione opzionale
L'operatore &&
può essere utilizzato per valutare un callback, solo se è passato:
function myMethod(cb) {
// This can be simplified
if (cb) {
cb();
}
// To this
cb && cb();
}
Naturalmente, il test precedente non convalida che cb
sia in realtà una function
e non solo un Object
/ Array
/ String
/ Number
.
Equazione astratta / disuguaglianza e conversione del tipo
Il problema
Gli operatori di uguaglianza e disuguaglianza astratta ( ==
e !=
) Convertono i loro operandi se i tipi di operando non corrispondono. Questa coercizione di tipo è una fonte comune di confusione sui risultati di questi operatori, in particolare, questi operatori non sono sempre transitivi come ci si aspetterebbe.
"" == 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
I risultati iniziano a dare un senso se si considera come JavaScript converte stringhe vuote in numeri.
Number(""); // 0
Number("0"); // 0
Number(false); // 0
La soluzione
Nell'istruzione false B
, entrambi gli operandi sono stringhe ( ""
e "0"
), quindi non ci sarà conversione di tipo e poiché ""
e "0"
non sono lo stesso valore, "" == "0"
è false
come previsto.
Un modo per eliminare comportamenti inaspettati qui è assicurarsi di confrontare sempre gli operandi dello stesso tipo. Ad esempio, se si desidera che i risultati del confronto numerico utilizzino la conversione esplicita:
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
Oppure, se vuoi il confronto delle stringhe:
var test = (a,b) => String(a) == String(b);
test("", 0); // false;
test("0", 0); // true
test("", "0"); // false;
Nota a margine : il Number("0")
e il new Number("0")
non sono la stessa cosa! Mentre il primo esegue una conversione di tipo, quest'ultimo crea un nuovo oggetto. Gli oggetti vengono confrontati per riferimento e non per valore, il che spiega i risultati di seguito.
Number("0") == Number("0"); // true;
new Number("0") == new Number("0"); // false
Infine, hai la possibilità di utilizzare operatori rigorosi di uguaglianza e disuguaglianza che non eseguiranno conversioni di tipo implicito.
"" === 0; // false
0 === "0"; // false
"" === "0"; // false
Ulteriori riferimenti a questo argomento possono essere trovati qui:
Quale operatore uguale (== vs ===) dovrebbe essere utilizzato nei confronti JavaScript? .
Matrice vuota
/* ToNumber(ToPrimitive([])) == ToNumber(false) */
[] == false; // true
Quando [].toString()
viene eseguito chiama [].join()
se esiste, o Object.prototype.toString()
altrimenti. Questo confronto restituisce true
perché [].join()
restituisce ''
che, forzato in 0
, è uguale a ToNumber falso.
Attenzione però, tutti gli oggetti sono veri e Array
è un'istanza di Object
:
// Internally this is evaluated as ToBoolean([]) === true ? 'truthy' : 'falsy'
[] ? 'truthy' : 'falsy'; // 'truthy'
Operazioni di confronto delle uguaglianze
JavaScript ha quattro diverse operazioni di confronto delle uguaglianze.
SameValue
Restituisce true
se entrambi gli operandi appartengono allo stesso Tipo e hanno lo stesso valore.
Nota: il valore di un oggetto è un riferimento.
È possibile utilizzare questo algoritmo di confronto tramite Object.is
(ECMAScript 6).
Esempi:
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
Questo algoritmo ha le proprietà di una relazione di equivalenza :
- Reflexivity :
Object.is(x, x)
ètrue
, per qualsiasi valorex
- Simmetria :
Object.is(x, y)
ètrue
se, e solo se,Object.is(y, x)
ètrue
, per qualsiasi valorex
ey
. - Transitività : Se
Object.is(x, y)
eObject.is(y, z)
sonotrue
, alloraObject.is(x, z)
è anchetrue
, per tutti i valorix
,y
ez
.
SameValueZero
Si comporta come SameValue, ma considera +0
e -0
uguali.
È possibile utilizzare questo algoritmo di confronto tramite Array.prototype.includes
(ECMAScript 7).
Esempi:
[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
Questo algoritmo ha ancora le proprietà di una relazione di equivalenza :
- Reflexivity :
[x].includes(x)
ètrue
, per qualsiasi valorex
- Simmetria :
[x].includes(y)
ètrue
se, e solo se,[y].includes(x)
ètrue
, per qualsiasi valorex
ey
. - Transitività : se
[x].includes(y)
e[y].includes(z)
sonotrue
, allora[x].includes(z)
è anchetrue
, per qualsiasi valorex
,y
ez
.
Rigoroso paragone di uguaglianza
Si comporta come SameValue, ma
- Considera
+0
e-0
uguali. - Considera
NaN
diverso da qualsiasi valore, incluso se stesso
È possibile utilizzare questo algoritmo di confronto tramite l'operatore ===
(ECMAScript 3).
Esiste anche l'operatore !==
(ECMAScript 3), che nega il risultato di ===
.
Esempi:
1 === 1; // true
+0 === -0; // true
NaN === NaN; // false
true === "true"; // false
false === 0; // false
1 === "1"; // false
null === undefined; // false
[] === []; // false
Questo algoritmo ha le seguenti proprietà:
- Simmetria :
x === y
ètrue
se, e solo se, y === xis
vero, for any values
xand
y`. - Transitività : se
x === y
y === z
sonotrue
, allorax === z
è anchetrue
, per qualsiasi valorex
,y
ez
.
Ma non è una relazione di equivalenza perché
-
NaN
non è riflessivo :NaN !== NaN
Confronto di uguaglianza astratta
Se entrambi gli operandi appartengono allo stesso Tipo, si comportano come il Parity Equality Comparison.
Altrimenti, li costringe come segue:
-
undefined
enull
sono considerati uguali - Quando si confronta un numero con una stringa, la stringa viene convertita in un numero
- Quando si confronta un booleano con qualcos'altro, il booleano viene forzato a un numero
- Quando si confronta un oggetto con un numero, una stringa o un simbolo, l'oggetto viene forzato a una primitiva
Se c'è stata una coercizione, i valori forzati vengono confrontati in modo ricorsivo. Altrimenti l'algoritmo restituisce false
.
È possibile utilizzare questo algoritmo di confronto tramite l'operatore ==
(ECMAScript 1).
Esiste anche l'operatore !=
(ECMAScript 1), che nega il risultato di ==
.
Esempi:
1 == 1; // true
+0 == -0; // true
NaN == NaN; // false
true == "true"; // false
false == 0; // true
1 == "1"; // true
null == undefined; // true
[] == []; // false
Questo algoritmo ha la seguente proprietà:
- Simmetria :
x == y
ètrue
se, e solo se,y == x
ètrue
, per qualsiasi valorex
ey
.
Ma non è una relazione di equivalenza perché
-
NaN
non è riflessivo :NaN != NaN
- La transitoria non regge, per esempio
0 == ''
e0 == '0'
, ma'' != '0'
Raggruppamento di più istruzioni logiche
È possibile raggruppare più istruzioni logiche booleane tra parentesi per creare una valutazione logica più complessa, particolarmente utile nelle istruzioni if.
if ((age >= 18 && height >= 5.11) || (status === 'royalty' && hasInvitation)) {
console.log('You can enter our club');
}
Potremmo anche spostare la logica raggruppata in variabili per rendere l'istruzione un po 'più breve e descrittiva:
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');
Si noti che in questo particolare esempio (e molti altri), il raggruppamento delle istruzioni con parentesi funziona allo stesso modo che se le rimuoviamo, basta seguire una valutazione logica lineare e vi ritroverete con lo stesso risultato. Preferisco usare la parentesi in quanto mi consente di capire meglio cosa intendo e potrebbe prevenire errori logici.
Conversioni di tipo automatico
Attenzione che i numeri possono essere accidentalmente convertiti in stringhe o NaN (Not a Number).
JavaScript è tipicamente digitato. Una variabile può contenere diversi tipi di dati e una variabile può cambiare il suo tipo di dati:
var x = "Hello"; // typeof x is a string
x = 5; // changes typeof x to a number
Quando si eseguono operazioni matematiche, JavaScript può convertire i numeri in stringhe:
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
Sottraendo una stringa da una stringa, non genera un errore ma restituisce NaN (Not a Number):
"Hello" - "Dolly" // returns NaN
Elenco degli operatori di confronto
Operatore | Confronto | Esempio |
---|---|---|
== | Pari | i == 0 |
=== | Valore e tipo uguali | i === "5" |
!= | Non uguale | i != 5 |
!== | Valore o tipo non uguale | i !== 5 |
> | Più grande di | i > 5 |
< | Meno di | i < 5 |
>= | Maggiore o uguale | i >= 5 |
<= | Meno o uguale | i <= 5 |
Campi di bit per ottimizzare il confronto dei dati multi-stato
Un campo bit è una variabile che contiene vari stati booleani come singoli bit. Un po 'rappresenterebbe vero, e off sarebbe falso. In passato i bit venivano usati di routine mentre salvavano la memoria e riducevano il carico di elaborazione. Sebbene la necessità di utilizzare il campo bit non sia più così importante, offrono alcuni vantaggi che possono semplificare molte attività di elaborazione.
Ad esempio l'input dell'utente. Quando si riceve l'input dai tasti di direzione di una tastiera su, giù, sinistra, destra è possibile codificare i vari tasti in una singola variabile con ciascuna direzione assegnata a un bit.
Esempio di lettura della tastiera tramite 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];
}
}
}
Esempio di lettura come una matrice
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";
}
}
Per accendere un bit usare bitwise o |
e il valore corrispondente al bit. Quindi, se desideri impostare il 2 ° bit, bitField |= 0b10
lo accenderà. Se desideri disattivare un bit usa bitwise e &
con un valore che ha tutto il bit richiesto. Usando 4 bit e disattivando il 2 ° bit di bitfield &= 0b1101;
Potresti dire che l'esempio sopra riportato sembra molto più complesso dell'assegnazione dei vari stati chiave a un array. Sì È un po 'più complesso da impostare, ma il vantaggio arriva quando si interroga lo stato.
Se vuoi testare se tutti i tasti sono attivi.
// 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])){
È possibile impostare alcune costanti per semplificare le cose
// 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
È quindi possibile testare rapidamente molti stati della tastiera
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
L'input da tastiera è solo un esempio. I bitfield sono utili quando si hanno vari stati che devono essere combinati in combinazione. Javascript può utilizzare fino a 32 bit per un campo bit. Usarli può offrire significativi aumenti delle prestazioni. Vale la pena essere familiari.