2560 votes

Est-ce que (a == 1 && a == 2 && a == 3) est évalué à vrai?

Modérateur remarque: Veuillez résister à l'envie de modifier le code ou de supprimer le présent avis. Le modèle de l'espace peut être une partie de la question et, par conséquent, ne devrait pas être altérée inutilement. Si vous êtes dans les "espaces est insignifiant" camp, vous devriez être en mesure d'accepter le code tel qu'il est.

Est-il possible qu' (a== 1 && a ==2 && a==3) pourrait évaluer à l' true en JavaScript?

C'est une question d'entrevue demandé par une grande entreprise de technologie. Il s'est passé deux semaines en arrière, mais je suis encore à essayer de trouver la réponse. Je sais que nous n'avons jamais écrire un tel code dans notre journée de travail de jour, mais je suis curieux.

3395voto

Kevin B Points 57721

Si vous profitez de combien de == fonctionne, vous pouvez simplement créer un objet avec une coutume toString (ou valueOf) fonction que les changements de quoi il en retourne chaque fois qu'il est utilisé tel qu'il remplit 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 la loose opérateur d'égalité. Lors de l'utilisation de lâche l'égalité, si l'un des opérandes est d'un type différent de l'autre, le moteur va tenter de convertir de l'un à l'autre. Dans le cas d'un objet sur la gauche et un certain nombre sur la droite, il tente de convertir l'objet d'un numéro en appelant d'abord valueOf si elle est exigible, et, à défaut, qu'il appellera toString. J'ai utilisé toString dans ce cas tout simplement parce que c'est ce qui m'est venu à l'esprit, valueOf aurait plus de sens. Si je l'ai retourné au lieu d'une chaîne d' toString, le moteur aurait ensuite tenté de convertir la chaîne en nombre de nous donner le même résultat, mais avec un peu plus de chemin.

2092voto

Jeff Points 2524

Je ne pouvais pas résister - autres réponses sont sans doute vrai, mais vous avez vraiment ne peut pas marcher passé le code suivant:

var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
    console.log("Why hello there!")
}

Remarque l'étrange espacement dans l' if déclaration (que j'ai copié à partir de votre question). C'est la demi-largeur Hangul (c'est le coréen pour ceux qui ne connaissent pas) qui est un espace Unicode caractère qui n'est pas interprété par l'ECMA script comme un caractère d'espace, ce qui signifie que c'est un caractère valide pour un identificateur. Par conséquent, il ya trois différentes variables, l'une avec le Hangul après l'un, un avec elle avant et la dernière avec juste une. Le remplacement de l'espace avec des _ pour des raisons de lisibilité, le même code devrait ressembler à ceci:

var a_ = 1;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
    console.log("Why hello there!")
}

Découvrez la validation sur Mathias nom de la variable du programme de validation. Si bizarre espacement a été inclus dans leur question, je suis sûr que c'est une astuce de ce genre de réponse.

Ne pas le faire. Sérieusement.

Edit: Il est venu à mon attention que (bien que n'étant pas autorisé à prendre le départ d'une variable) le liant sans chasse et de largeur Nulle de non-menuisier personnages sont également autorisés dans les noms de variable - voir Abrutissant JavaScript avec zéro de caractères de largeur - les avantages et les inconvénients?.

Ce serait semblable à la suivante:

var a= 1;
var a‍= 2; //one zero-width character
var a‍‍= 3; //two zero-width characters (or you can use the other one)
if(a==1&&a‍==2&&a‍‍==3) {
    console.log("Why hello there!")
}

631voto

Jonas Wilms Points 52419

C'EST POSSIBLE!

var i = 0;

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

Il utilise un getter à l'intérieur d'un with déclaration laissez - a évaluer à trois valeurs différentes.

... ce n'est pas pour autant cette fonction doit être utilisée dans le code réel...

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

  var i = 0;

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

538voto

georg Points 52691

Exemple sans getters ou valueOf:

a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);

Cela fonctionne parce qu' == invoque toString qui demande .join pour les Tableaux.

Une autre solution, à l'aide de Symbol.toPrimitive qui est un ES6 équivalent de toString/valueOf:

let i = 0;
let a = { [Symbol.toPrimitive]: () => ++i };

console.log(a == 1 && a == 2 && a == 3);

268voto

ocomfd Points 2708

Si on lui demande si c'est possible (et non pas obligatoire), il peut demander à "un" de retourner un nombre aléatoire. Ce serait vrai s'il génère 1, 2 et 3 de manière séquentielle.

 with({
  get a() {
    return Math.floor(Math.random()*4);
  }
}){
  for(var i=0;i<1000;i++){
    if (a == 1 && a == 2 && a == 3){
      console.log("after " + (i+1) + " trials, it becomes true finally!!!");
      break;
    }
  }
} 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X