小云是一枚還沒有脫髮的程式設計師,最近看到ES熱度這麼高,決定蹭一波熱度。
ES7新增的特性
- Array.prototype.includes
- **
**
小云首先看到了ES7中新增的**運算子,心中暗喜:這麼簡單?
8 ** 3 // 512
Math.pow(8, 3) // 512
複製程式碼
但是小云喜歡瞎折騰,於是他又敲了下列程式碼:
2 ** 2 ** 0 // 2
複製程式碼
結果竟然是2,小云帶著疑惑查了查資料,原來**運算子是右結合的:
(2 ** 2) ** 0 // 1
複製程式碼
小云終於得到了自己預期的結果,而且還發現了底數的前面不能緊跟一元運算子,即使是+也不行。
Array.prototype.includes
Tip: 為什麼這個方法不叫contains呢?因為一些Bug,它被重新命名為includes
接下來,小云開始學習includes方法:
[1, 2, 1].includes(1) // true
複製程式碼
小云又敲下了之前用來判斷陣列中的元素是否存在的程式碼:
if ([1, 2, 1].indexOf(1) !== -1) {
// true
}
複製程式碼
哇!終於可以擺脫那個令人討厭的!== -1了。
難道這兩個方法僅僅是在返回值上有區別嗎?小云這次決定不再瞎折騰,直接移步ES7文件。
數個小時之後,小云要開始他的表演了。
ES標準的相等比較演算法
- The Abstract Equality Comparison Algorithm (==)
- The Strict Equality Comparison Algorithm (===)
- SameValue (Object.is())
- SameValueZero (暫未提供API)
對於前兩個大家再熟悉不過了,在我剛學JS的時候,只是通過自己長期累積的經驗去區別兩者的差異:
[1, 2, 3] == '1,2,3' // true
['1'] == 1 // true
複製程式碼
以至於遇到上述情況驚歎不已,但是瞭解原理之後,一切變得那麼的簡單。
The Abstract Equality Comparison Algorithm
- 當型別相同時,特殊性在於NaN, -0, 0。
NaN == NaN // false
-0 == 0 // true
複製程式碼
- 當型別不同時,第一條準則是:null與undefined相等
- 當型別不同時,第二條準則是:所有的比較最終多會轉化為數值的比較,而它轉化的優先順序是Boolean => Object => String
前面兩條不難理解,通過['1'] == true比較的過程,熟悉一下第三條規則:
- 將右邊的Boolean型別轉化為Number型別, 轉化為 ['1'] == 1
- 將左邊的Object型別轉化為原始值,轉化為 '1' == 1
- 將左邊的String型別轉化為Number型別, 轉化為 1 == 1
這時你再遇到:
[] == false // true
複製程式碼
是不是很輕鬆就知道結果了。
The Strict Equality Comparison Algorithm
對於這個演算法需要注意的地方是在Number型別的比較上:
NaN === NaN // false
-0 === 0 // true
複製程式碼
Tip: 上述方法的分析多是基於ES5.1,在ES6中都有細微的改變,比如加入Symbol的比較。
SameValue
對於熟練使用ES6的小夥伴,多知道Object.is()這個方法:
Object.is(NaN, NaN) // true
Object.is(0, -0) // false
複製程式碼
而Object.is內部採用的比較演算法就是SameValue(x, y),而它與 === 的區別也正是這兩種情況。
SameValueZero
但是你在使用es6中有沒有疑惑這種情況:
const s = new Set()
s.add(0)
s.add(NaN)
s.has(-0) // true
s.has(NaN) // true
複製程式碼
是不是與上述的三種演算法的表現多不一樣,這就是第四種比較演算法SameValueZero,它與SameValue的區別主要在於0與-0是否相等。
所以你在實踐includes方法時,遇到:
const a = [0, NaN]
a.includes(-0) // true
a.includes(NaN) // true
複製程式碼
就不用大驚小怪了,因為includes內部使用的比較演算法就是SameValueZero。
參考文獻
喜歡本文的小夥伴們,歡迎關注我的訂閱號超愛敲程式碼,檢視更多內容.