(a== 1 &&amp ; a ==2 &&amp ; a==3) peut-il jamais être évalué comme vrai ?

Note du modérateur: Veuillez résister à l'envie de modifier le code ou de supprimer cet avis. Le modèle d'espace blanc peut faire partie de la question et ne devrait donc pas être modifié inutilement. Si vous êtes dans le camp de "l'espace blanc est insignifiant", vous devriez pouvoir accepter le code tel quel.

Est-il possible que (a== 1 &&amp ; a ==2 &&amp ; a==3) soit évalué à vrai en JavaScript ?

Il s'agit d'une question d'entretien posée par une grande entreprise technologique. Cela s'est passé il y a deux semaines, mais j'essaie toujours de trouver la réponse. Je sais que nous n'écrivons jamais un tel code dans notre travail quotidien, mais je suis curieux.

Solution

Si vous tirez parti de [how == works] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#Loose_equality_using), vous pouvez simplement créer un objet avec une fonction toString (ou valueOf) personnalisée qui modifie ce qu'elle renvoie à chaque fois qu'elle est utilisée de manière à satisfaire les trois conditions.

const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}

La raison pour laquelle cela fonctionne est due à l'utilisation de l'opérateur d'égalité libre. Lors de l'utilisation de l'égalité libre, si l'un des opérandes est d'un type différent de l'autre, le moteur tentera de convertir l'un en l'autre. Dans le cas d'un objet à gauche et d'un nombre à droite, il essaiera de convertir l'objet en nombre en appelant d'abord valueOf s'il est appelable, et sinon, il appellera toString. J'ai utilisé toString dans ce cas simplement parce que c'est ce qui m'est venu à l'esprit, valueOf aurait été plus logique. Si j'avais retourné une chaîne de caractères à partir de toString, le moteur aurait alors essayé de convertir la chaîne en un nombre, ce qui nous aurait donné le même résultat final, mais avec un chemin un peu plus long.

Commentaires (19)

C'EST POSSIBLE !

var i = 0;

with({
  get a() {
    return ++i;
  }
}) {
  if (a == 1 && a == 2 && a == 3)
    console.log("wohoo");
}

Ceci utilise un getter à l'intérieur d'une instruction with pour que a soit évalué à trois valeurs différentes.

... cela ne signifie toujours pas que cela devrait être utilisé dans du code réel...

Pire encore, cette astuce fonctionne également avec l'utilisation de ===.

  var i = 0;

  with({
    get a() {
      return ++i;
    }
  }) {
    if (a !== a)
      console.log("yep, this is printed.");
  }
Commentaires (12)

Cela peut être accompli en utilisant ce qui suit dans la portée globale. Pour nodejs, utilisez global au lieu de window dans le code ci-dessous.

var val = 0;
Object.defineProperty(window, 'a', {
  get: function() {
    return ++val;
  }
});
if (a == 1 && a == 2 && a == 3) {
  console.log('yay');
}

Cette réponse abuse des variables implicites fournies par la portée globale dans le contexte d'exécution en définissant un getter pour récupérer la variable.

Commentaires (6)