Kan (a== 1 && a ==2 && a==3) ooit evalueren naar waar?

Moderator note: Gelieve de drang te weerstaan om de code aan te passen of deze mededeling te verwijderen. Het patroon van witruimte kan deel uitmaken van de vraag en daarom moet er niet onnodig aan geknoeid worden. Als je in het "whitespace is insignificant" kamp zit, zou je de code moeten kunnen accepteren zoals die is.

Is het ooit mogelijk dat (a== 1 && a ==2 && a==3) kan evalueren naar true in JavaScript?

Dit is een interview vraag gesteld door een groot tech bedrijf. Het gebeurde twee weken geleden, maar ik'ben nog steeds op zoek naar het antwoord. Ik weet dat we nooit zulke code schrijven in ons dagelijks werk, maar ik'ben nieuwsgierig.

Oplossing

Als je gebruik maakt van hoe == werkt, kun je eenvoudig een object maken met een aangepaste toString (of valueOf) functie die elke keer dat hij gebruikt wordt verandert wat hij teruggeeft, zodat hij aan alle drie de voorwaarden voldoet.

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

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

De reden dat dit werkt is door het gebruik van de loose equality operator. Bij het gebruik van losse gelijkheid, als een van de operanden van een ander type is dan de andere, zal de engine proberen om de ene te converteren naar de andere. In het geval van een object aan de linkerkant en een getal aan de rechterkant, zal de engine proberen om het object om te zetten naar een getal door eerst valueOf aan te roepen als deze oproepbaar is, en als dat niet lukt, zal de engine toString aanroepen. Ik heb toString in dit geval gebruikt omdat dat in me opkwam, valueOf zou logischer zijn. Als ik in plaats daarvan een string had teruggegeven van toString, dan zou de engine hebben geprobeerd om de string om te zetten in een getal, wat ons hetzelfde eindresultaat zou geven, zij het met een iets langer pad.

Commentaren (19)

HET IS MOGELIJK!

var i = 0;

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

Dit gebruikt een getter in een with statement om a te laten evalueren naar drie verschillende waarden.

... dit betekent nog steeds niet dat dit in echte code gebruikt moet worden...

Nog erger, deze truc werkt ook met het gebruik van ==.

  var i = 0;

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

Het kan worden bereikt met het volgende in de globale scope. Voor nodejs gebruik global in plaats van window in de code hieronder.

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

Dit antwoord maakt misbruik van de impliciete variabelen die door het globale bereik in de uitvoeringscontext worden verschaft door een getter te definiëren om de variabele op te halen.

Commentaren (6)