Примітка модератора:** Будь ласка, не піддавайтеся бажанню відредагувати код або видалити це повідомлення. Шаблон пробілів може бути частиною питання і тому його не слід змінювати без необхідності. Якщо Ви перебуваєте в таборі прихильників "пробіли несуттєві", Ви повинні мати можливість прийняти код як є.
Чи можливо, що (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
, рушій спробував би перетворити рядок в число, що дало б нам той самий кінцевий результат, хоча і з трохи довшим шляхом.
ЦЕ МОЖЛИВО!
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.");
}
У глобальній області видимості це можна зробити, використовуючи наступне. Для nodejs
використовуйте global
замість window
в наведеному нижче коді.
var val = 0;
Object.defineProperty(window, 'a', {
get: function() {
return ++val;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log('yay');
}
Ця відповідь зловживає неявними змінними, що надаються глобальною областю видимості в контексті виконання, визначаючи геттер для отримання змінної.