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.