3 septembre 2023

Opérateurs logiques

Il y a trois opérateurs logiques en JavaScript : || (OR), && (AND), ! (NOT), ?? (Coalescence des nulles). Nous couvrons ici les trois premiers, l’opérateur ?? est dans l’article suivant.

Bien qu’ils soient appelés “logiques”, ils peuvent être appliqués à des valeurs de tout type, pas seulement booléennes. Le résultat peut également être de tout type.

Voyons les détails.

|| (OR)

L’opérateur “OR” est représenté avec deux symboles de ligne verticale :

result = a || b;

En programmation classique, le OU logique est destiné à manipuler uniquement les valeurs booléennes. Si l’un de ses arguments est true, alors il renvoie true, sinon il renvoie false.

En JavaScript, l’opérateur est un peu plus compliqué et puissant. Mais voyons d’abord ce qui se passe avec les valeurs booléennes.

Il existe quatre combinaisons logiques possibles :

alert( true  || true  ); // true
alert( false || true  ); // true
alert( true  || false ); // true
alert( false || false ); // false

Comme on peut le voir, le résultat est toujours true sauf pour le cas où les deux opérandes sont false.

Si un opérande n’est pas booléen, il est converti en booléen pour l’évaluation.

Par exemple, un nombre 1 est traité comme true, un nombre 0 – comme false :

if (1 || 0) { // fonctionne comme si ( true || false )
  alert( 'truthy!' );
}

La plupart du temps, OR || est utilisé dans une instruction if pour tester si l'une des conditions données est correcte.

Par exemple :

let hour = 9;

if (hour < 10 || hour > 18) {
  alert( 'The office is closed.' );
}

Nous pouvons passer plus de conditions :

let hour = 12;
let isWeekend = true;

if (hour < 10 || hour > 18 || isWeekend) {
  alert( 'The office is closed.' ); // c'est le weekend
}

OR "||" cherche la première valeur vraie

La logique décrite ci-dessus est quelque peu classique. Maintenant, apportons les fonctionnalités “supplémentaires” de JavaScript.

L’algorithme étendu fonctionne comme suit.

En cas de multiples valeurs liées par OR :

result = value1 || value2 || value3;

L’opérateur OR || fait ce qui suit :

  • Évaluez les opérandes de gauche à droite.
  • Pour chaque opérande, il le convertit en booléen. Si le résultat est true, arrêtez et retournez la valeur d’origine de cet opérande.
  • Si tous les autres opérandes ont été évalués (c’est-à-dire que tous étaient false), renvoyez le dernier opérande.

Une valeur est renvoyée sous sa forme d’origine, sans conversion.

En d’autres termes, une chaîne de OR || renvoie la première valeur true ou la dernière valeur si aucune valeur true n’a été trouvée.

Par exemple :

alert( 1 || 0 ); // 1 (1 est vrai)

alert( null || 1 ); // 1 (1 est la première valeur vraie)
alert( null || 0 || 1 ); // 1 (la première valeur vraie)

alert( undefined || null || 0 ); // 0 (tous faux, renvoie la dernière valeur)

Cela conduit à des usages intéressants par rapport à un “OR pur, classique, booléen uniquement”.

  1. Obtenir la première valeur vraie dans la liste des variables ou des expressions.

    Par exemple, nous avons les variables firstName, lastName et nickName, toutes optionnelles (c’est-à-dire peut être indéfini ou avoir des valeurs fausses).

    Utilisons OR || pour choisir celui qui contient les données et l’afficher (ou Anonymous si rien n’est défini) :

    let firstName = "";
    let lastName = "";
    let nickName = "SuperCoder";
    
    alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder

    Si toutes les variables étaient fausses, ce serait "Anonymous" qui apparaîtrait.

  2. Évaluation des courts-circuits.

    Une autre caractéristique de l’opérateur OR || est l’évaluation dite de “court-circuit”.

    Cela signifie que || traite ses arguments jusqu’à ce que la première valeur de vérité soit atteinte, puis la valeur est renvoyée immédiatement, sans même toucher l’autre argument.

    L’importance de cette fonctionnalité devient évidente si un opérande n’est pas seulement une valeur, mais une expression avec un effet secondaire, comme une affectation de variable ou un appel de fonction.

    Dans l’exemple ci-dessous, seul le deuxième message est imprimé :

    true || alert("not printed");
    false || alert("printed");

    Dans la première ligne, l’opérateur OR || arrête l’évaluation immédiatement après avoir vu true, de sorte que alert n’est pas exécuté.

    Parfois, les gens utilisent cette fonctionnalité pour exécuter des commandes uniquement si la condition sur la partie gauche est fausse.

&& (AND)

L’opérateur AND est représenté avec deux esperluettes && :

result = a && b;

En programmation classique, AND retourne true si les deux opérandes sont true et false dans les autres cas :

alert( true  && true  ); // true
alert( false && true  ); // false
alert( true  && false ); // false
alert( false && false ); // false

Un exemple avec if:

let hour = 12;
let minute = 30;

if (hour == 12 && minute == 30) {
  alert( 'Time is 12:30' );
}

Tout comme pour OR, toute valeur est autorisée en tant qu’opérande de AND :

if (1 && 0) { // évalué comme true && false
  alert( "Ne marchera pas, car le résultat est faux" );
}

AND “&&” cherche la première valeur fausse

En cas de multiples valeurs liées par AND :

result = value1 && value2 && value3;

L’opérateur AND && effectue les opérations suivantes :

  • Évalue les opérandes de gauche à droite.
  • Pour chaque opérande, il le convertit en booléen. Si le résultat est false, arrêtez et retournez la valeur d’origine de cet opérande.
  • Si tous les autres opérandes ont été évalués (c’est-à-dire tous étaient vrais), retournez le dernier opérande.

En d’autres termes, une chaîne de AND && renvoie la première valeur false ou la dernière valeur si aucune valeur false n’a été trouvée.

Les règles ci-dessus sont similaires à OR. La différence est que AND retourne la première valeur false tandis que OR renvoie la première valeur true.

Exemples :

// si le premier opérande est vrai,
// AND retourne le second opérande :
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// si le premier opérande est faux,
// AND le retourne. Le deuxième opérande est ignoré
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0

Nous pouvons également transmettre plusieurs valeurs à la suite sur une même ligne. Voyez comment le premier faux est retourné :

alert( 1 && 2 && null && 3 ); // null

Lorsque toutes les valeurs sont vraies, la dernière valeur est renvoyée :

alert( 1 && 2 && 3 ); // 3, la dernière
La précédence de AND && est supérieure à OR ||

La priorité de l’opérateur AND && est supérieure à OR ||.

Donc, le code a && b || c && d est essentiellement le même que si && était entre parenthèses: (a && b) || (c && d).

Ne remplacez pas if par || ou &&

Parfois, les gens utilisent l’opérateur AND && comme "plus court pour écrire if".

Par exemple :

let x = 1;

(x > 0) && alert( 'Greater than zero!' );

L’action dans la partie droite de && ne s’exécutera que si l’évaluation lui parvient. C’est-à-dire que seulement si (x > 0) est vrai.

Donc, nous avons une analogie pour :

let x = 1;

if (x > 0) alert( 'Greater than zero!' );

Bien que la variante avec && semble plus courte, if est plus évidente et a tendance à être un peu plus lisible. Nous recommandons donc d’utiliser chaque construction dans son but : utilisez if si nous voulons if et utilisez && si nous voulons ET.

! (NOT)

L’opérateur booléen NOT est représenté par un point d’exclamation !.

La syntaxe est assez simple :

result = !value;

L’opérateur accepte un seul argument et effectue les opérations suivantes :

  1. Convertit l’opérande en type booléen : true/false.
  2. Renvoie la valeur inverse.

Par exemple :

alert( !true ); // false
alert( !0 ); // true

Un double NOT !! est parfois utilisé pour convertir une valeur en type booléen :

alert( !!"non-empty string" ); // true
alert( !!null ); // false

C’est-à-dire que le premier NOT convertit la valeur en booléen et retourne l’inverse, et que le second NOT l’inverse encore. À la fin, nous avons une conversion valeur à booléen simple.

Il existe un moyen un peu plus verbeux de faire la même chose – une fonction Boolean intégrée :

alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false

La précédence de NOT ! est la plus élevée de tous les opérateurs binaire, il est donc toujours exécuté en premier, avant les autres.

Exercices

importance: 5

Qu’est-ce que le code ci-dessous va sortir ?

alert( null || 2 || undefined );

La réponse est 2, c’est la première valeur vraie.

alert( null || 2 || undefined );
importance: 3

Qu’est-ce que le code ci-dessous va sortir ?

alert( alert(1) || 2 || alert(3) );

La réponse : d’abord 1 puis 2.

alert( alert(1) || 2 || alert(3) );

Règle importante à retenir : L’appel de l’alert ne renvoie pas de valeur. Ou, en d’autres termes, il retourne undefined.

  1. Le premier OR || évalue son opérande gauche alert(1). Cela affiche le premier message avec 1.
  2. L’alert retourne undefined, donc OR passe au deuxième opérande en recherchant une valeur vraie.
  3. Le deuxième opérande 2 est vrai, donc l’exécution est interrompue, 2 est renvoyé puis affiché par l’alerte externe.

Il n’y aura pas de 3, car l’évaluation n’atteint pas l’alert (3).

importance: 5

Qu’est-ce que ce code va afficher ?

alert( 1 && null && 2 );

La réponse : null, car c’est la première valeur false de la liste.

alert(1 && null && 2);
importance: 3

Qu’est-ce que ce code va afficher ?

alert( alert(1) && alert(2) );

La réponse : 1, et ensuite undefined.

alert( alert(1) && alert(2) );

L’appel de l’alert renvoie undefined (il affiche juste un message, donc il n’ya pas de retour significatif dans le code).

À cause de cela, && évalue l’opérande gauche (sortie 1), et s’arrête immédiatement, car undefined est une valeur false. Et comme && recherche la première valeur fausse et la retourne, donc il s’arrête là.

importance: 5

Quel sera le résultat ?

alert( null || 2 && 3 || 4 );

La réponse : 3.

alert( null || 2 && 3 || 4 );

La priorité de AND && est supérieure à OR ||, elle s’exécute donc en premier.

Le résultat de 2 && 3 = 3, donc l’expression devient :

null || 3 || 4

Maintenant, le résultat est la première valeur vraie : 3.

importance: 3

Ecrivez une condition "if" pour vérifier que l’age est compris entre 14 et 90 ans inclus.

“Inclus” signifie que l’age peut atteindre les 14 ou 90 ans.

if (age >= 14 && age <= 90)
importance: 3

Ecrivez une condition if pour vérifier que l’age n’est PAS compris entre 14 et 90 ans inclus.

Créez deux variantes: la première utilisant NOT !, La seconde – sans ce dernier.

La première variante :

if (!(age >= 14 && age <= 90))

La seconde variante :

if (age < 14 || age > 90)
importance: 5

Lesquelles de ces alertes vont s’exécuter ?

Quels seront les résultats des expressions à l’intérieur de if (...) ?

if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );

La réponse: le premier et le troisième vont s’exécuter.

Details:

// S'éxécute
// le résultat de -1 || 0 = -1, vrai
if (-1 || 0) alert( 'first' );

// Ne s'éxécute pas
// -1 && 0 = 0, faux
if (-1 && 0) alert( 'second' );

// S'éxécute
// L'opérateur && a une précédence plus élevée que ||
// donc -1 && 1 s'exécute en premier, nous donnant la chaîne :
// null || -1 && 1  ->  null || 1  ->  1
if (null || -1 && 1) alert( 'third' );
importance: 3

Écrivez le code qui demande une connexion avec prompt.

Si le visiteur entre "Admin", puis prompt pour un mot de passe, si l’entrée est une ligne vide ou Esc – affichez “Canceled”, s’il s’agit d’une autre chaîne de caractères – alors affichez “I don’t know you”.

Le mot de passe est vérifié comme suit :

  • S’il est égal à “TheMaster”, alors affichez “Welcome!”,
  • Une autre chaînede caractères – affichez “Wrong password”,
  • Pour une chaîne de caractères vide ou une entrée annulée, affichez “Canceled”.

Le schéma :

Veuillez utiliser des blocs if imbriqués. Attention à la lisibilité globale du code.

Astuce: passer une entrée vide à un prompt renvoie une chaîne de caractères vide ''. En pressant ESC lors d’un prompt cela retourne null.

Exécuter la démo

let userName = prompt("Who's there?", '');

if (userName === 'Admin') {

  let pass = prompt('Password?', '');

  if (pass === 'TheMaster') {
    alert( 'Welcome!' );
  } else if (pass === '' || pass === null) {
    alert( 'Canceled' );
  } else {
    alert( 'Wrong password' );
  }

} else if (userName === '' || userName === null) {
  alert( 'Canceled' );
} else {
  alert( "I don't know you" );
}

Notez les retraits verticaux à l’intérieur des blocs if. Ils ne sont techniquement pas nécessaires, mais rendent le code plus lisible.

Carte du tutoriel

Commentaires

lire ceci avant de commenter…
  • Si vous avez des améliorations à suggérer, merci de soumettre une issue GitHub ou une pull request au lieu de commenter.
  • Si vous ne comprenez pas quelque chose dans l'article, merci de préciser.
  • Pour insérer quelques bouts de code, utilisez la balise <code>, pour plusieurs lignes – enveloppez-les avec la balise <pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen…)