Чи може (a== 1 && a ==2 && a==3) коли-небудь набути значення true?

Примітка модератора:** Будь ласка, не піддавайтеся бажанню відредагувати код або видалити це повідомлення. Шаблон пробілів може бути частиною питання і тому його не слід змінювати без необхідності. Якщо Ви перебуваєте в таборі прихильників "пробіли несуттєві", Ви повинні мати можливість прийняти код як є.

Чи можливо, що (a== 1 && a ==2 && a==3) може оцінитись в істину в JavaScript?

Це питання на співбесіді з великою технологічною компанією. Це було два тижні тому, але я все ще намагаюся знайти відповідь. Я знаю, що ми ніколи не пишемо такого коду в нашій повсякденній роботі, але мені цікаво.

Рішення

Якщо ви скористаєтеся як працює ==, ви можете просто створити об'єкт з користувацькою функцією toString (або valueOf), яка змінює те, що вона повертає при кожному використанні так, щоб це задовольняло всім трьом умовам.

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

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

Причиною такої роботи є використання оператора нечіткої рівності. При використанні нестрогої рівності, якщо один з операндів має інший тип, ніж інший, рушій спробує перетворити один в інший. У випадку з об'єктом зліва і числом справа, він спробує перетворити об'єкт в число, спочатку викликавши valueOf, якщо він доступний для виклику, і якщо це не вдасться, він викличе toString. Я використовував toString в цьому випадку просто тому, що це те, що прийшло в голову, valueOf мав би більше сенсу. Якби я замість цього повернув рядок з toString, рушій спробував би перетворити рядок в число, що дало б нам той самий кінцевий результат, хоча і з трохи довшим шляхом.

Коментарі (19)

ЦЕ МОЖЛИВО!

var i = 0;

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

Тут використовується геттер всередині оператора with, щоб дозволити a обчислити три різні значення.

... це ще не означає, що це потрібно використовувати в реальному коді...

Що ще гірше, цей трюк також буде працювати з використанням ===.

  var i = 0;

  with({
    get a() {
      return ++i;
    }
  }) {
    if (a !== a)
      console.log("yep, this is printed.");
  }
Коментарі (12)

У глобальній області видимості це можна зробити, використовуючи наступне. Для nodejs використовуйте global замість window в наведеному нижче коді.

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

Ця відповідь зловживає неявними змінними, що надаються глобальною областю видимості в контексті виконання, визначаючи геттер для отримання змінної.

Коментарі (6)