Забележка на модератора: Моля, не се поддавайте на желанието да редактирате кода или да премахнете това съобщение. Моделът на белите полета може да е част от въпроса и затова не трябва да се променя излишно. Ако сте в лагера на "белите полета са незначителни", би трябвало да можете да приемете кода в този му вид.
Възможно ли е някога (a== 1 && a ==2 && a==3)
да се оцени като true
в 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");
}
Това използва getter в оператора 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');
}
Този отговор злоупотребява с имплицитните променливи, предоставени от глобалния обхват в контекста на изпълнение, като дефинира getter за извличане на променливата.