Vai (a== 1 &&& a ==2 && a==3) kādreiz var novērtēt kā true?

Moderatora piezīme: Lūdzu, atturieties no vēlmes rediģēt kodu vai dzēst šo paziņojumu. Balto laukumu raksts var būt daļa no jautājuma, tāpēc nevajadzētu to nevajadzīgi izmainīt. Ja esat "baltās vietas ir nenozīmīgas" nometnē, jums vajadzētu būt iespējai pieņemt kodu tādu, kāds tas ir.

Vai ir iespējams, ka (a== 1 &&& a ==2 &&& a==3) varētu būt true JavaScript valodā?

Šis ir intervijas jautājums, ko uzdeva liels tehnoloģiju uzņēmums. Tas notika pirms divām nedēļām, bet es joprojām mēģinu atrast atbildi. Es zinu, ka ikdienas darbā mēs nekad nerakstām šādu kodu, bet es esmu ziņkārīgs.

Risinājums

Ja jūs izmantosiet kā darbojas ==, jūs varētu vienkārši izveidot objektu ar pielāgotu toString (vai valueOf) funkciju, kas katru reizi, kad tā tiek izmantota, mainītu atgrieztās vērtības tā, lai tā atbilstu visiem trim nosacījumiem.

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

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

Tas darbojas tāpēc, ka tiek izmantots brīvās vienlīdzības operators. Ja, izmantojot brīvas vienlīdzības operatoru, viens no operandiem ir cita tipa nekā otrs, dzinējs mēģinās konvertēt vienu no tiem uz otru. Ja kreisajā pusē ir objekts, bet labajā pusē - skaitlis, tas mēģinās pārveidot objektu par skaitli, vispirms izsaucot valueOf, ja tas ir izsaucams, un, ja tas nebūs iespējams, izsauks toString. Šajā gadījumā es izmantoju toString tikai tāpēc, ka tas man ienāca prātā, jo valueOf būtu jēgpilnāk. Ja es tā vietā no toString būtu atgriezis virkni, tad dzinējs būtu mēģinājis pārvērst virkni skaitlī, iegūstot tādu pašu galarezultātu, taču ar nedaudz garāku ceļu.

Komentāri (19)

TAS IR IESPĒJAMS!

var i = 0;

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

Šeit tiek izmantots getter with izteikuma iekšpusē, lai a varētu novērtēt uz trim dažādām vērtībām.

... tas vēl nenozīmē, ka to vajadzētu izmantot reālā kodā...

Vēl sliktāk, šis triks darbojas arī ar ===.

  var i = 0;

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

To var izdarīt, globālajā darbības jomā izmantojot. Tālāk sniegtajā kodā nodejs kodu loga vietā lietojiet global.

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

Šī atbilde ļaunprātīgi izmanto netiešos mainīgos, ko nodrošina globālā darbības joma izpildes kontekstā, definējot getter, lai iegūtu mainīgo.

Komentāri (6)