iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 11
0
自我挑戰組

你為什麼不問問神奇 JavaScript 呢?系列 第 11

Day11 - 寬鬆相等 VS. 嚴格相等

第七章的最後部分

四天弄下來,不管是 明確的、隱含的 還是相等性。
已經是處在被問不倒的狀態。
就算答錯,也能馬上意會,哪裡出問題。(阿不是問不倒?)

一句話回想四個部分的重點吧!

  1. 了解轉到特定型別時,JS 背後運作的方式。 ex: ToString, ToNumber, ToPrimitive, falsy。
  2. 明確的強制轉型,除了明顯的以外,還有業界或高手認可的明確。 ex: +, -, *, /, ~, |, parseInt(), !!
  3. 隱含的強制轉型,發生的地方,還有自動幫忙轉的模式。 ex: valueOf(), toString(), &&, ||
  4. 相等性,等等聊吧~

寬鬆相等 VS. 嚴格相等

正確的描述是:「==允許在比較中強制轉型,=== 不允許。」

所以,只要型別不同,=== 肯定不相同。

效能只差百萬分之一秒。若想強制轉型兩邊,直接用 == 是沒問題的。

抽象相等性

了解== 強制轉型兩側如何轉型。

先列出例外

  • NaN 不等於自己。
  • +0 與 -0 相等。

1. 比較字串與數字

x == y x = "1" x = 1
y = "1" true ToNumber(y)
y = 1 ToNumber(x) true

hint: ToNumber(),先找 valueOf(),再找 toString()。

2. 比較布林與其他值

先 ToNumber( Boolean ),再與其他值比較。

所以,不要用 == true 和 == false。
他們只會被轉成 1 和 0,在和其他值比較。
(判斷真假值不是這樣用低!)

3. 比較:null 與 undefined

不管怎樣都是 true。

拿來判斷 null or undefined 最好不過。因為其他全都是 false。

4. 比較:物件與非物件

x y
String or Number {} ToPrimitive(y)
{} String or Number ToPrimitive(x)

沒有 Boolean 是因為不管怎樣先轉他,得到 number。

邊緣情況

  1. 能轉數字就轉數字。
  2. null 和 undefined 看對面是不是 null 或 undefined。
  3. 物件會轉成基本型別值,若沒有就回傳 "[object object]"。
"0" == null;       // Rule 2
"0" == undefined;  // Rule 2
"0" == false;      // number == number
"0" == NaN;        // NaN != anything
"0" == 0;          // number == number
"0" == "";         // string != string

false == 0;        // number == number
false == "";       // number == number
false == [];       // number == number
false == {};       // number != "[object object]"

"" == 0;           // number == number
"" == [];          // number == number
"" == {};          // number != "[object object]"

瘋狂版!

[] == ![];   // number == number( from false )
2 == [2];    // number == number ( from string)
"" == [null];// "" == ""
0 == "\n";   // true 詳情看書。

安全地使用隱含的強制轉型

  1. 避免其中一邊是 ture or false。
  2. 避免其中一邊可能出現 []、""、0 。

在這兩種情況下請務必使用 ===

這裡你可以了解所有的相等性。

抽象的關係式比較

大於小於 兩側運算元比較的隱含轉型。

規格只定義了兩個部分。

  1. 兩邊都是 String
  2. 其他

然後,不管大小於,JavaScript 都是以小於來處理。 a > b ==> a < b

var a = [42];
var b = ["43"];

a < b ; // true
b < a ; // false

array 會先呼叫 ToPrimitive,然後只要其中一方不是 string,就會轉為 Number 值。

所以,只要兩邊轉型後,都是 string,就會以 逐字 比較。

var a = ["42"]
var b = ["043"]

a < b ; // false

讓我們看看 object 吧!

var a = { c: 42 };
var b = { c: 43 };

a < b ; // false
b < a ; // false

因為 物件經過隱含轉型後,會變成 "[object object]"。

但是!

a == b ; // false

這要了解前面說 == 比較的對象是誰。
其實是 object 所指向的記憶體位置參考 (referance)。

但是!

a <= b; // true
a >= b; // true

對於 a >= b 來說,他是先估算 a < b,再做否定。
(這邊真的是有點雷,如果不知道規則真的想破頭。)

小結:如果要在關係式比較上,更準確知道比較型別,先明確的強制轉型吧。當然,如果你很了他隱含的強制轉型,就不用理會了。

總結

  1. 明確的強制轉型 - 自己轉,增加可讀性和可維護性。
  2. 隱含的強制轉型 - JS 轉,為了可讀性而擁有了一些需要了解的副作用。
  3. 強制轉型 請有意識地用,特別是 隱含 的強制轉型。

總之,規則很多,不管背不背的起來,就先測試,還是要用身體體驗呢?

祝 武運昌隆!

( 明天是週末了耶!!)

參考資料

  1. 你所不知道的 JS
  2. Github - dorey/JavaScript-Equality-Table

上一篇
Day10 - 隱含的強制轉型
下一篇
Day12 - 文法
系列文
你為什麼不問問神奇 JavaScript 呢?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言