[JavaScriptWeird]No.53 「==」和「===」

前言

直接講結論:「不管什麼時候,都應該只使用三個等於來進行比較,除非是進行教學或者是-故意的。」

「==」和「===」的差異

使用「==」進行比較

首先我們必須了解「==」實際上在做什麼,這部分的觀念其實在[JavaScriptWeird]No.16 強制型轉[JavaScriptWeird]No.17 比較運算子都有提到一些。

使用「==」進行比較時,「==」會嘗試將左右兩邊的型別根據某個規則,嘗試將型別轉成一致並進行比較,最後回傳比較結果。

1
2
3
var a = 1;  
var b = '1';
console.log(a == b); // true

使用「===」進行比較

如果使用「===」進行比較,就不會觸發型別轉換,因此結果會比較接近我們預期的那樣。

1
2
3
var a = 1;  
var b = '1';
console.log(a === b); // false

「==」和「===」的比較表

可以上 JS Comparison Table 查詢各種比較結果。

雙等號比較表

三等號比較表

為什麼我們應該只使用「===」比較

因為使用「==」會觸發型別轉換,而且透過雙等號比較表可以得知其中規則相當複雜,可能會跑出一些非預期的結果。

而使用「===」的話,因為不會觸發型別轉換,較容易預測結果,而且比較表也相對好記憶。

原始型別與物件型別的差異

之前提到一些原始型別 (Primitive Types) 與物件型別 (Object Types) 的差異,這邊將提到另外一個差異:

  • 與原始型別不同,物件型別是比較記憶體位址
    1
    2
    3
    var obj = { number: 1 }  
    var obj2 = obj;
    console.log(obj === obj2); // true

眼尖的你應該會發現,比較表上明明寫著兩個物件相比都是 false ,那麼為什麼這邊會是 true 呢?

我們可以把這段 code 在記憶體的樣子畫出來:

可以發現變數 objobj2 都是指向同一個記憶體位址,因此第三行的比較其實是「比較兩個變數指向的記憶體位址」,既然兩個變數都指向同一個記憶體位址,那麼答案自然會是 true 。

同理,修改一下例子,並畫圖了解:

1
2
3
var obj = { number: 1 }  
var obj2 = { number: 1 }
console.log(obj === obj2); // false

由前一個例子可知,物件型別之間的比較比的是記憶體的位址,從這張圖看來,兩個 {} 物件在記憶體中的位置並不相同,所以比較的結果才會是 false。

這樣就可驗證為什麼只要是物件型別之間的比較都會是 false 了,因為只要產生一個新物件,就會是不同的記憶體位址。

而有哪些是物件型別呢?

只要不屬於原始型別的那六種,都是物件型別。這倒是可以用很簡單的二分法來判斷。

特殊的例子

NaN (Not a Number)

顧名思義 NaN 就是非數字(Not a Number),但是很弔詭的是:

  • 使用 typeof NaN 得到的結果會是數字型別 (number)

    1
    console.log(typeof NaN); // number
  • 而 NaN 本身也無法使用「===」或「==」與自己比較

    1
    console.log(NaN === NaN); // false
  • 神奇的是如果你拿數字型別跟 NaN 相比也會是 false

    1
    console.log(typeof(1) === NaN); // false

NaN 如何產生的

相當容易產生,只要 Javascript 發生自動型轉或者我們主動將值轉換成數字時,當中混有無法轉成數值的東西時,就會產生 NaN。

因此 NaN 是個相當可怕的東西,我們應該避免產生 NaN。

使用 isNaN() 檢查是否為 NaN

因為我們沒辦法從上面任何方式判斷是否為 NaN ,但是幸好還有 isNaN() 可以使用,使用方法相當容易:

1
2
var test = 1 + 's';  
console.log(isNaN(test)); // true

這樣子就能判斷是否為 NaN 了,另外這是 MDN 對於 NaN 的解釋

不支援 isNaN() 的瀏覽器的因應措施

很不幸的 isNaN() 好像不是所有瀏覽器都支援,但是我們可以透過 polyfill 令不支援 isNaN() 的瀏覽器也可以使用。

而幸運的是,這可以在 MDN 上找到。

感恩 MDN 讚嘆 MDN

心得

這是上完保哥課程後的第一篇記錄文,很高興能用到課堂上的知識來加深這些觀念的印象,而最棒的是我看的這支影片居然也用同樣的方式來介紹這些觀念,果然是高手所見略同呢。

我覺得對初心者來說,比起生硬的文字,最容易有印象的果然還是畫圖。

而且是必須要親自畫,不能只有看。而從「讀出程式碼」到畫出來的過程中,也可以了解自己觀念理解的正不正確,因為只要唸出來的是錯的,代表你想的也是錯的,自然畫出來的圖也會是錯的,這時候就會產生BUG。

0%