Les opérateurs binaires

Résumé Support

En regardant le code source de @preact/signals-core je suis tombé sur le code suivant.

// Flags for Computed and Effect. const RUNNING = 1 << 0; const NOTIFIED = 1 << 1; const OUTDATED = 1 << 2; const DISPOSED = 1 << 3; const HAS_ERROR = 1 << 4; const TRACKING = 1 << 5; // ... if (effect.flags & DISPOSED) { }

Ce n'est pas forcément un code qu'on a l'habitude de voir dans le développement web. Aussi je vous propose de décrypter ces opérateurs binaires et voir leur utilisation dans un cas concret.

Opérateur de décalage <<

L’opérateur de décalage à gauche << est un opérateur binaire qui décale les bits d’un nombre vers la gauche d’un certain nombre de positions.

Binaire
1 0000 0001
1 << 0 0000 0001
1 << 1 0000 0010
1 << 2 0000 0100

Dans le cas de l'exemple, l'opérateur est utilisé pour créer des nombre binaires avec le bit 1 décalé d'un certain nombre sur la gauche.

Opérateur OR |

L'opérateur binaire OR retourne vrai (1) si au moins l'une des deux valeurs est vraie (1).

A B A OR B
0 0 0
0 1 1
1 0 1
1 1 1

Dans le cas de notre code, cet opérateur va permettre de créer une variable qui combine plusieurs valeurs.

const LOG = 1 << 0 const WARN = 1 << 1 const ERROR = 1 << 2 const flag = ERROR | WARNING

Opérateur AND &

L'opérateur binaire AND retourne vrai (1) si les des deux valeurs sont vraies (1).

A B A AND B
0 0 0
0 1 0
1 0 0
1 1 1

Dans le cas de notre code, cet opérateur va être utilisé dans une condition

if (flag & WARNING) { // Le drapeau contient WARNING }

Opérateur NOT ~

L'opérateur binaire NOT inverse les bits.

Nombre Bits.
10 0000 1010
~10 1111 0101

Dans le cas du code il peut être utilisé en combinaison de l'opérateur & pour retirer un élément dans notre drapeau.

flag &= ~WARNING

Analogie avec l'approche tableau

Pour résumer les opérateurs binaires peuvent être utilisés en remplacement d'une liste pour gérer une liste d'état / drapeau. L'opérateur OR est utilisé pour combiner plusieurs valeurs en une seule.

// En binaire flag = WARNING | ERROR // En tableau flag = ["WARNING", "ERROR"]

Cet opérateur peut aussi être utilisé lors d'un assignement pour ajouter une valeur.

// En binaire flag |= WARNING // En tableau flag.push("WARNING")

L'opérateur AND va servir à vérifier la présence d'une valeur dans notre drapeau.

// En binaire if (flag & WARNING) { } // En tableau if (flag.includes("WARNING")) { }

Enfin la combinaison de l'opérateur NOT et AND permet de retirer facilement une valeur dans le drapeau.

// En binaire flag &= ~WARNING // En tableau flag = flag.filter(v => v !== "WARNING")

Pourquoi ?

L'utilisation des opérateurs binaire permet de sauvegarder l'information dans un espace mémoire plus réduit en n'utilisant qu'un octet pour sauvegarder une combinaison de valeurs mais on notera plusieurs petits inconvénients.

  • Cette approche marche bien si on a moins de 8 valeurs possible pour notre drapeau
  • Le déboggage peut être un peu plus difficile avec un nombre plutôt qu'une chaine de caractère.