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 esempio 0/0 )
  • document.all ¹ (contesto del browser)

Tutto il resto è considerato "vero" .

¹ violazione intenzionale delle specifiche ECMAScript

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 confronto x == y , dove x ed y sono valori, produce true o false . Tale confronto viene eseguito come segue:

  1. Se Type(x) è uguale a Type(y) , allora:
  • un. Restituisce il risultato dell'esecuzione del Confronto di uguaglianza rigorosa x === y .
  1. Se x è null e y undefined è undefined , restituisce true .
  2. Se x undefined è undefined e y è null , restituisce true .
  3. Se Type(x) è Number e Type(y) è String , restituisce il risultato del confronto x == ToNumber(y) .
  4. Se Type(x) è String e Type(y) è Number , restituisce il risultato del confronto ToNumber(x) == y .
  5. Se Type(x) è Boolean , restituisce il risultato del confronto ToNumber(x) == y .
  6. Se Type(y) è Boolean , restituisce il risultato del comparison x == ToNumber(y) .
  7. Se Type(x) è String , Number o Symbol e Type(y) è Object , restituisce il risultato del confronto x == ToPrimitive(y) .
  8. Se Type(x) è Object e Type(y) è String , Number o Symbol , restituisce il risultato del confronto ToPrimitive(x) == y .
  9. 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 nascondersi undefined da tale ambito (anche se le cose possono ancora essere undefined )
  • 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");

nullundefined 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 shadowing Array o Number .
  • Evita di impostare qualcosa di undefined . Se si desidera rimuovere una barra delle proprietà da un oggetto foo , delete foo.bar; anziché.
  • L'identificatore di test dell'esistenza foo contro undefined potrebbe generare un errore di riferimento , utilizzare invece typeof 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

6

È 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
6

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
6

È 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? .

Equality astratta (==)

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 valore x
  • Simmetria : Object.is(x, y) è true se, e solo se, Object.is(y, x) è true , per qualsiasi valore x e y .
  • Transitività : Se Object.is(x, y) e Object.is(y, z) sono true , allora Object.is(x, z) è anche true , per tutti i valori x , y e z .

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 valore x
  • Simmetria : [x].includes(y) è true se, e solo se, [y].includes(x) è true , per qualsiasi valore x e y .
  • Transitività : se [x].includes(y) e [y].includes(z) sono true , allora [x].includes(z) è anche true , per qualsiasi valore x , y e z .

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 === x is vero , for any values x and y`.
  • Transitività : se x === y y === z sono true , allora x === z è anche true , per qualsiasi valore x , y e z .

Ma non è una relazione di equivalenza perché

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 e null 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 valore x e y .

Ma non è una relazione di equivalenza perché

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.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow