1. 程式人生 > >(a ==1 && a== 2 && a==3) 有可能是 true 嗎?

(a ==1 && a== 2 && a==3) 有可能是 true 嗎?

一個有趣的問題:

在 JavaScript 中, (a ==1 && a== 2 && a==3) 是否有可能為 true ?

這是一道我被某科技公司問到的面試題。發生在兩週之前,我仍然在努力尋找答案。

我知道我們從來不會在日常工作中寫出這樣的程式碼,但我對問題的答案仍然十分很好奇。

解法一:

利用鬆散相等運算子 == 的工作原理,你可以簡單地建立一個帶有自定義toString( 或者 valueOf)函式的物件,在每一次使用它時候改變它所的返回值,使其滿足所有三個條件。

JavaScript
12345678910consta
={i:1,toString:function(){returna.i++;}}if(a==1&&a==2&&a==3){console.log('Hello World!');}// Hello World!

>之所以會得到如此結果,是由於表示式中使用了鬆散相等的運算子 ==。使用鬆散相等時,如果其中一個運算元與另一個型別不同,則 JS 引擎將嘗試將一個操作轉換為另一個型別。在左邊物件、右邊的數字的情況下,它會嘗試將物件轉換為一個數,首先通過呼叫 valueOf 如果是可呼叫的。否則,它會呼叫toString方法。我使用toString僅僅是因為它是我的第一反應,valueOf

 會更合理。如果我不從toString返回一個字串(而是返回數字),JS 引擎會嘗試將字串轉換為一個數字,雖然有一個稍長的路徑,但它仍然會給我們同樣的結果。

解法二:

我不可否認——其他答案無疑是正確的,但你真的不能過錯下面的程式碼:

JavaScript
1 2 3 4 5 6 vara=1; vara=2; vara=3; if(a==1&&a==2&&a==3){ console.log("Why hello there!") }

請注意if 語句中的奇怪間距。它是半寬度韓文=,=。這是一個 Unicode 空格字元,但是 ECMAScript 不將其解釋為一個空格 —— 這意味著它是一個有效的識別符號。因此有三個完全不同的變數,一個是a

後加半寬度韓文,一個是a, 一個是a前加半寬度韓文。。。

用下劃線 _ 替代半寬度韓文,增加可讀性,相同的程式碼看起來像這樣:

JavaScript
123456vara_=1;vara=2;var_a=3;if(a_==1&&a==2&&_a==3){console.log("Why hello there!")}

解法三:

這是完全可能的!

JavaScript
1 2 3 4 5 6 7 8 9 varval=0; Object.defineProperty(window,'a',{ get:function(){ return++val; } }); if(a==1&&a==2&&a==3){ console.log('yay'); }

使用一個get,讓 a 的返回值為三個不同的值。然而這並不意味著我們應該在真正的程式碼中使用。。。

And so on …

總結

1. 利用鬆散相等運算子 == 的原理,自定義 toString 和 valueOf 返回對應值

2. 利用半寬度韓文等特殊字元,玩“障眼法”,本質上其實並沒有做到題設

3. 劫持 JS 物件的 getter,不過這種方式對於嚴格相等 === 同樣有效