本系列文章已重新編修,並在加入部分 ES6 新篇章後集結成書,有興趣的朋友可至天瓏書局選購,感謝大家支持。
購書連結 https://www.tenlong.com.tw/products/9789864344130
讓我們再次重新認識 JavaScript!
昨天看到朋友傳了一個在 stack overflow 看到的有趣問題:
Can (a ==1 && a== 2 && a==3) ever evaluate to true?
發問的人表示,他去參加了某個公司的面試,面試官問他要怎麼樣讓 JavaScript 的
(a == 1 && a == 2 && a == 3)
結果為 true 。
也就是說,希望結果會像這樣:

來,猜猜看,到底施了什麼魔法才能讓判斷式 (a == 1 && a == 2 && a == 3) 成立?
想一想,先別急著看連結內的解答。
.
.
.
.
.
.
有答案了嗎? 好,我們來看看原文的最佳解答是怎麼做的吧!
const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}
if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}
看出來為什麼了嗎?
複習一下,我們在「重新認識 JavaScript」系列文的
兩篇文章當中,曾經為各位介紹過「比較運算子」與「Boolean 的自動轉型」特性對吧?
先看 if 的條件判斷式
if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}
因為 && 運算子會先將左側的結果轉換成 Boolean ,並檢查是否為 ture,如果為 true 再將 && 右側的值回傳。
所以像上面這樣的寫法,我們可以拆分成:
// 當 a == 1, a == 2, a == 3 都成立時才執行 console.log
if( a == 1 ) {
  if( a == 2 ) {
    if( a == 3 ) {
      console.log('Hello World!');
    }
  }
}
注意到了嗎?
這裡有個重點, if 判斷式內的檢查是用 == 而非 ===。
換句話說,當我們在做 ( a == 1 ) 的判斷時,這個 a 會被自動轉型成「字串」的型態再做判斷。 那麼,來看看 a。
const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}
這裡可以看到 a 是個物件的型態。 系列文曾提過,在物件的情況下,會先透過物件的 valueOf() 方法先求得對應的數值,若物件沒有 valueOf() 方法的話,則會透過 toString() 轉型再進行比較。
好,所以說 a.toString() 會得到什麼? a.i++。
a.i 的初始值是 1,所以 a.i++ 回傳的結果是什麼? 還是 1。 (注意 ++ 的位置)
所以第一關 (a == 1) 的結果通過了。
由於因為剛剛執行了 a.i++,所以此時 a.i 實質的結果是 2。
而第二關的 ( a == 2 ) 又會再做一次 a.i++,得到的結果是 2,所以又通過了。
那麼第三關的 ( a == 3 ) 相信不用解說,當然也會得到 3。
於是最後就完成了:
(a == 1 && a == 2 && a == 3) === true
這樣的結果了。

平常工作如果看到這樣程式的話,我一定會大罵花惹發,但是以觀念測試的角度來說,我覺得這是個不錯的情境題喔。
這篇 Stackflow 的問答討論熱度好像很高,今天到哪裡都看的到 
(() => {
    "use strict";
    Object.defineProperty(this, "a", {
        "get": () => {
            Object.defineProperty(this, "a", {
                "get": () => {
                    Object.defineProperty(this, "a", {
                        "get": () => {
                            return 3;
                        }
                    });
                    return 2;
                },
                configurable: true
            });
            return 1;
        },
        configurable: true
    });
    if (a == 1 && a == 2 && a == 3) {
        document.body.append("Yes, it’s possible.");
    }
})();
這個真不知道該說是非常認真還是怎樣了哈哈
每 get 一次就複寫 get return 出來的 value 的意思 XD
借用這個方法改寫,把 function 提出來,以後就可以大量製造這種 value 了(誤

可惜XD node 無法改,只好用 valueOf,只有轉型時才能用
