Recherche…


Remarques

Lorsque vous utilisez une coercition, les valeurs suivantes sont considérées comme "falsy" :

  • false
  • 0
  • "" (chaîne vide)
  • null
  • undefined
  • NaN (pas un nombre, par exemple 0/0 )
  • document.all ¹ (contexte du navigateur)

Tout le reste est considéré comme "véridique" .

¹ violation délibérée de la spécification ECMAScript

Opérateurs logiques avec des booléens

var x = true,
    y = false;

ET

Cet opérateur renverra true si les deux expressions ont la valeur true. Cet opérateur booléen utilisera un court-circuit et n'évaluera pas y si x évalué comme false .

x && y;

Cela retournera faux, car y est faux.

OU

Cet opérateur renverra true si l'une des deux expressions a la valeur true. Cet opérateur booléen utilisera la mise en court-circuit et y ne sera pas évalué si x évalué à true .

x || y;

Cela retournera vrai, car x est vrai.

NE PAS

Cet opérateur renverra false si l'expression à droite est évaluée à true et renvoie true si l'expression à droite est fausse.

!x;

Cela retournera false, car x est vrai.

Égalité abstraite (==)

Les opérandes de l'opérateur d'égalité abstraite sont comparés après avoir été convertis en un type commun. Comment cette conversion se produit est basée sur les spécifications de l'opérateur:

Spécification pour l'opérateur == :

7.2.13 Comparaison d'égalité abstraite

La comparaison x == y , où x et y sont des valeurs, produit true ou false . Une telle comparaison est effectuée comme suit:

  1. Si Type(x) est identique à Type(y) , alors:
  • une. Renvoie le résultat de l'exécution de Strict Equality Comparison x === y .
  1. Si x est null et que y est undefined , retournez true .
  2. Si x n'est undefined et que y est null , retournez true .
  3. Si Type(x) est Number et Type(y) est String , retournez le résultat de la comparaison x == ToNumber(y) .
  4. Si Type(x) est String et Type(y) est Number , retournez le résultat de la comparaison ToNumber(x) == y .
  5. Si Type(x) est Boolean , retournez le résultat de la comparaison ToNumber(x) == y .
  6. Si Type(y) est Boolean , retournez le résultat de la comparison x == ToNumber(y) .
  7. Si Type(x) est soit String , Number , ou Symbol et Type(y) est Object , renvoyez le résultat de la comparaison x == ToPrimitive(y) .
  8. Si Type(x) est Object et Type(y) est String , Number ou Symbol , renvoyez le résultat de la comparaison ToPrimitive(x) == y .
  9. Retourne false .

Exemples:

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

Opérateurs relationnels (<, <=,>,> =)

Lorsque les deux opérandes sont numériques, ils sont comparés normalement:

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

Lorsque les deux opérandes sont des chaînes, elles sont comparées lexicographiquement (selon l’ordre alphabétique):

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

Lorsqu'une opérande est une chaîne et que l'autre est un nombre, la chaîne est convertie en nombre avant la comparaison:

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

Lorsque la chaîne est non numérique, la conversion numérique renvoie NaN (pas un nombre). La comparaison avec NaN renvoie toujours false :

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

Mais soyez prudent lorsque vous comparez une valeur numérique avec des chaînes null , undefined ou vides:

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

Lorsqu'un opérande est un objet et que l'autre est un nombre, l'objet est converti en nombre avant la comparaison. Ainsi, null est un cas particulier car Number(null);//0

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

Inégalité

L'opérateur != Est l'inverse de l'opérateur == .
Renvoie true si les opérandes ne sont pas égaux.
Le moteur JavaScript essaiera de convertir les deux opérandes en types correspondants s'ils ne sont pas du même type. Note: si les deux opérandes ont des références internes différentes en mémoire, alors false sera renvoyé.

Échantillon:

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

Dans l'exemple ci - dessus, 1 != '1' est false parce que, un type de numéro primitif est comparé à un char valeur. Par conséquent, le moteur Javascript ne se soucie pas du type de données de la valeur RHS.

Opérateur !== est l'inverse de l'opérateur === . Renvoie true si les opérandes ne sont pas égaux ou si leurs types ne correspondent pas.

Exemple:

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

Opérateurs logiques avec des valeurs non booléennes (coercition booléenne)

Logical OR ( || ), lisant de gauche à droite, évaluera la première valeur de vérité . Si aucune valeur de vérité n'est trouvée, la dernière valeur est renvoyée.

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'

Logical AND ( && ), en lisant de gauche à droite, évaluera à la première valeur de falsy . Si aucune valeur de falsey n'est trouvée, la dernière valeur est renvoyée.

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

Cette astuce peut être utilisée, par exemple, pour définir une valeur par défaut sur un argument de fonction (antérieur à 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

Gardez juste à l'esprit que pour les arguments, 0 et (dans une moindre mesure) la chaîne vide sont aussi souvent des valeurs valides qui devraient pouvoir être explicitement passées et remplacer une valeur par défaut, ce qui, avec ce modèle, ne le sera pas (parce qu'elles sont fausses ).

Null et indéfini

Les différences entre null et undefined

égalité abstraite de part de partage null et undefined == mais pas d'égalité stricte === ,

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

Ils représentent des choses légèrement différentes:

  • undefined représente l' absence d'une valeur , par exemple avant la création d'une propriété identifiant / objet ou dans la période entre la création du paramètre identifiant / fonction et son premier ensemble, le cas échéant.
  • null représente l' absence intentionnelle d'une valeur pour un identifiant ou une propriété déjà créé.

Ce sont différents types de syntaxe:

  • undefined est une propriété de l'objet global , généralement immuable dans la portée globale. Cela signifie que partout où vous pouvez définir un identifiant autre que dans l'espace de nommage global pourrait cacher undefined de ce champ (bien que les choses peuvent encore être undefined )
  • null est un littéral de mot , donc sa signification ne peut jamais être modifiée et tenter de le faire va générer une erreur .

Les similitudes entre null et undefined

null et undefined sont tous deux falsifiés.

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

Ni null ni undefined égal à false (voir cette question ).

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

Utiliser undefined

  • Si la portée actuelle ne peut pas être approuvée, utilisez quelque chose qui est considéré comme indéfini , par exemple void 0; .
  • Si undefined est ombré par une autre valeur, il est tout aussi mauvais que Shadow Array ou Number .
  • Évitez de définir quelque chose comme undefined . Si vous souhaitez supprimer une barre de propriété d'un objet foo , delete foo.bar; au lieu.
  • L'identifiant de test d'existence foo contre undefined pourrait typeof foo une erreur de référence , mais utiliser typeof foo contre "undefined" .

Propriété NaN de l'objet global

NaN (" N ot a N umber") est une valeur spéciale définie par la norme IEEE pour l'arithmétique en virgule flottante , qui est utilisée lorsqu'une valeur non numérique est fournie, mais qu'un nombre est attendu ( 1 * "two" ), ou lorsqu'un calcul n'a pas de résultat de number valide ( Math.sqrt(-1) ).

Toute égalité ou comparaison relationnelle avec NaN renvoie false , même en la comparant à elle-même. Parce que, NaN est supposé dénoter le résultat d’un calcul absurde, et en tant que tel, il n’est pas égal au résultat d’autres calculs absurdes.

(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

Les comparaisons non égales renvoient toujours true :

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

Vérifier si une valeur est NaN

6

Vous pouvez tester une valeur ou une expression pour NaN en utilisant la fonction 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

Vous pouvez vérifier si une valeur est NaN en la comparant à elle-même:

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

Vous pouvez utiliser le polyfill suivant pour Number.isNaN() :

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

En revanche, la fonction globale isNaN() renvoie true non seulement pour NaN , mais aussi pour toute valeur ou expression qui ne peut pas être forcée dans un nombre:

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 définit un algorithme de «similitude» appelé SameValue qui, depuis ECMAScript 6, peut être Object.is avec Object.is . Contrairement à la comparaison == et === , l'utilisation d' Object.is() traitera NaN comme identique à lui-même (et -0 comme pas identique à +0 ):

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

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

Vous pouvez utiliser le polyfill suivant pour Object.is() (à partir de 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;
    }
  };
}

Points à noter

NaN lui-même est un nombre, ce qui signifie qu'il n'est pas égal à la chaîne "NaN", et le plus important (mais peut-être de manière non intuitive):

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

Court-circuit dans les opérateurs booléens

L'opérateur-opérateur ( && ) et l'opérateur-opérateur ( || ) utilisent un court-circuit pour empêcher tout travail inutile si le résultat de l'opération ne change pas avec le travail supplémentaire.

Dans x && y , y ne sera pas évalué si x évalué comme false , car l'expression entière est garantie être false .

En x || y , y ne sera pas évalué si x évalué à true , car il est garanti que toute l'expression est true .

Exemple avec des fonctions

Prenez les deux fonctions suivantes:

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

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

Exemple 1

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

Sortie:

'T'
'F'

Exemple 2

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

Sortie:

'F'

Exemple 3

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

Sortie:

'T'

Exemple 4

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

Sortie:

'F'
'T'


Court-circuit pour éviter les erreurs

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

Ligne A: si vous inversez la commande, la première instruction conditionnelle empêchera l'erreur sur la seconde en ne l'exécutant pas si elle génère l'erreur

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

Mais ne devrait être utilisé que si vous attendez undefined

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

Court-circuit pour fournir une valeur par défaut

Le || L'opérateur peut être utilisé pour sélectionner une valeur "Vérité" ou la valeur par défaut.

Par exemple, cela peut être utilisé pour garantir qu'une valeur nullable est convertie en une valeur non nullable:

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

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

Ou pour retourner la première valeur véridique

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

La même chose peut être utilisée pour reculer plusieurs fois:

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

Court-circuit pour appeler une fonction optionnelle

L'opérateur && peut être utilisé pour évaluer un rappel, uniquement s'il est transmis:

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

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

Bien sûr, le test ci-dessus ne valide pas que cb est en fait une function et pas seulement un Object / Array / String / Number .

Egalité abstraite / inégalité et conversion de type

Le problème

Les opérateurs d'égalité abstraite et d'inégalité ( == et != ) Convertissent leurs opérandes si les types d'opérandes ne correspondent pas. Ce type de coercition est une source commune de confusion sur les résultats de ces opérateurs, en particulier, ces opérateurs ne sont pas toujours transitifs comme on pourrait s’y attendre.

"" ==  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

Les résultats commencent à avoir un sens si vous considérez comment JavaScript convertit les chaînes vides en nombres.

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

La solution

Dans la déclaration false B , les deux opérandes sont des chaînes ( "" et "0" ), il n'y aura donc pas de conversion de type et puisque "" et "0" n'ont pas la même valeur, "" == "0" est false comme prévu.

Une façon d'éliminer les comportements inattendus est de toujours comparer les opérandes du même type. Par exemple, si vous souhaitez que les résultats de la comparaison numérique utilisent une conversion explicite:

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 

Ou, si vous voulez une comparaison de chaînes:

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

Note : Le Number("0") et le new Number("0") ne sont pas la même chose! Alors que le premier effectue une conversion de type, le second crée un nouvel objet. Les objets sont comparés par référence et non par valeur, ce qui explique les résultats ci-dessous.

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

Enfin, vous avez la possibilité d'utiliser des opérateurs d'égalité et d'inégalité stricts qui n'effectueront aucune conversion de type implicite.

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

Vous trouverez d'autres références à ce sujet ici:

Quel est l'opérateur égal (== vs ===) à utiliser dans les comparaisons JavaScript? .

Égalité abstraite (==)

Tableau vide

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

Lorsque [].toString() est exécuté, il appelle [].join() s'il existe, ou Object.prototype.toString() sinon. Cette comparaison renvoie true car [].join() renvoie '' qui, forcé dans 0 , est égal à false ToNumber .

Attention cependant, tous les objets sont véridiques et Array est une instance de Object :

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

Opérations de comparaison d'égalité

JavaScript a quatre opérations de comparaison d'égalité différentes.

SameValue

Il renvoie true si les deux opérandes appartiennent au même type et ont la même valeur.

Note: la valeur d'un objet est une référence.

Vous pouvez utiliser cet algorithme de comparaison via Object.is (ECMAScript 6).

Exemples:

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

Cet algorithme a les propriétés d'une relation d'équivalence :

  • Réflexivité : Object.is(x, x) est true , pour toute valeur x
  • Symétrie : Object.is(x, y) est true si et seulement si Object.is(y, x) est true pour toutes les valeurs x et y .
  • Transitivité : si Object.is(x, y) et Object.is(y, z) sont true , Object.is(x, z) est également true pour toutes les valeurs x , y et z .

SameValueZero

Il se comporte comme SameValue, mais considère que +0 et -0 sont égaux.

Vous pouvez utiliser cet algorithme de comparaison via Array.prototype.includes (ECMAScript 7).

Exemples:

[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

Cet algorithme a toujours les propriétés d'une relation d'équivalence :

  • Réflexivité : [x].includes(x) est true , pour toute valeur x
  • Symétrie : [x].includes(y) est true si et seulement si [y].includes(x) est true pour toutes les valeurs x et y .
  • Transitivité : Si [x].includes(y) et [y].includes(z) sont true , alors [x].includes(z) est également true pour toutes les valeurs x , y et z .

Comparaison stricte de l'égalité

Il se comporte comme SameValue, mais

  • Considère que +0 et -0 sont égaux.
  • Considère NaN différent de toute valeur, y compris lui-même

Vous pouvez utiliser cet algorithme de comparaison via l'opérateur === (ECMAScript 3).

Il y a aussi l'opérateur !== (ECMAScript 3), qui annule le résultat de === .

Exemples:

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

Cet algorithme a les propriétés suivantes:

  • Symétrie : x === y est true si, et seulement si, y === x is vrai , for any values x and y`.
  • Transitivité : Si x === y et y === z sont true , alors x === z est également true pour toutes les valeurs x , y et z .

Mais n'est pas une relation d'équivalence car

Comparaison d'égalité abstraite

Si les deux opérandes appartiennent au même type, il se comporte comme la comparaison stricte d'égalité.

Sinon, il les contraint comme suit:

  • undefined et null sont considérés comme égaux
  • Lorsque vous comparez un nombre avec une chaîne, la chaîne est forcée à un nombre
  • En comparant un booléen avec autre chose, le booléen est forcé à un nombre
  • Lors de la comparaison d'un objet avec un nombre, une chaîne ou un symbole, l'objet est contraint à une primitive

S'il y avait coercition, les valeurs coercitives sont comparées récursivement. Sinon, l'algorithme retourne false .

Vous pouvez utiliser cet algorithme de comparaison via l'opérateur == (ECMAScript 1).

Il y a aussi l'opérateur != (ECMAScript 1), qui annule le résultat de == .

Exemples:

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

Cet algorithme a la propriété suivante:

  • Symétrie : x == y est true si et seulement si y == x est true pour toutes les valeurs x et y .

Mais n'est pas une relation d'équivalence car

Regroupement de plusieurs instructions logiques

Vous pouvez regrouper plusieurs instructions logiques booléennes entre parenthèses afin de créer une évaluation logique plus complexe, particulièrement utile dans les instructions if.

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

Nous pourrions également déplacer la logique groupée vers des variables pour raccourcir et décrire l’instruction:

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');

Notez que dans cet exemple particulier (et beaucoup d'autres), le regroupement des instructions avec des parenthèses fonctionne de la même manière que si nous les supprimions, suivez simplement une évaluation de logique linéaire et vous vous retrouverez avec le même résultat. Je préfère utiliser les parenthèses, car cela me permet de comprendre plus clairement ce que je voulais et de prévenir les erreurs de logique.

Conversions de type automatique

Attention, les nombres peuvent être convertis accidentellement en chaînes ou en NaN (pas un nombre).

JavaScript est tapé librement. Une variable peut contenir différents types de données et une variable peut modifier son type de données:

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

Lors d'opérations mathématiques, JavaScript peut convertir des nombres en chaînes:

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

Soustraire une chaîne à une chaîne ne génère pas d'erreur mais renvoie NaN (pas un nombre):

"Hello" - "Dolly"    // returns NaN

Liste des opérateurs de comparaison

Opérateur Comparaison Exemple
== Égal i == 0
=== Valeur et type égaux i === "5"
!= Inégal i != 5
!== Valeur ou type non égal i !== 5
> Plus grand que i > 5
< Moins que i < 5
>= Meilleur que ou égal i >= 5
<= Inférieur ou égal i <= 5

Champs de bits pour optimiser la comparaison de données multi-états

Un champ de bits est une variable qui contient différents états booléens en tant que bits individuels. Un peu sur représenterait vrai, et off serait faux. Dans le passé, les champs de bits étaient couramment utilisés car ils économisaient de la mémoire et réduisaient la charge de traitement. Bien que le besoin d'utiliser des champs de bits ne soit plus si important, ils offrent certains avantages qui peuvent simplifier de nombreuses tâches de traitement.

Par exemple, saisie utilisateur. Lors de la saisie des touches de direction du clavier vers le haut, le bas, la gauche et la droite, vous pouvez encoder les différentes clés en une seule variable avec chaque direction assignée à un bit.

Exemple de lecture du clavier via 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];
        }
    }    
}

Exemple de lecture en tableau

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";
    }    
}

Pour activer un bit, utilisez bitwise ou | et la valeur correspondant au bit. Donc, si vous souhaitez définir le 2ème bit, bitField |= 0b10 l’ bitField |= 0b10 . Si vous souhaitez désactiver un peu, utilisez bitwise et & avec une valeur qui a tous le bit requis. Utiliser 4 bits et éteindre le bit bit bitfield &= 0b1101;

Vous pouvez dire que l'exemple ci-dessus semble beaucoup plus complexe que d'attribuer les différents états clés à un tableau. Oui, c'est un peu plus complexe à mettre en place mais l'avantage vient quand on interroge l'état.

Si vous voulez tester si toutes les clés sont en place.

// 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])){

Vous pouvez définir des constantes pour faciliter les choses

// 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

Vous pouvez ensuite tester rapidement plusieurs états de clavier

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

La saisie au clavier n'est qu'un exemple. Les champs de bits sont utiles lorsque vous devez combiner différents états. Javascript peut utiliser jusqu'à 32 bits pour un champ de bits. Leur utilisation peut offrir des augmentations de performances significatives. Ils valent la peine d'être familiers.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow