iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 46
3
Modern Web

重新認識 JavaScript系列 第 37

重新認識 JavaScript 番外篇 (7) - 判斷式 (a == 1 && a == 2 && a == 3) 結果為 true ?

昨天看到朋友傳了一個在 stack overflow 看到的有趣問題:
Can (a ==1 && a== 2 && a==3) ever evaluate to true?

發問的人表示,他去參加了某個公司的面試,面試官問他要怎麼樣讓 JavaScript 的

(a == 1 && a == 2 && a == 3)

結果為 true

也就是說,希望結果會像這樣:

https://ithelp.ithome.com.tw/upload/images/20180118/20065504VOBjy43fJ4.jpg

來,猜猜看,到底施了什麼魔法才能讓判斷式 (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

這樣的結果了。

https://ithelp.ithome.com.tw/upload/images/20180118/20065504psjURjqtjw.jpg

平常工作如果看到這樣程式的話,我一定會大罵花惹發,但是以觀念測試的角度來說,我覺得這是個不錯的情境題喔。


上一篇
重新認識 JavaScript 番外篇 (6) - 網頁的生命週期
系列文
重新認識 JavaScript37

1 則留言

0
阿陰
iT邦新手 5 級 ‧ 2018-01-18 20:13:27

這篇 Stackflow 的問答討論熱度好像很高,今天到哪裡都看的到 /images/emoticon/emoticon37.gif

(() => {
    "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

我要留言

立即登入留言