ES2015中有四種相等算法:
- 抽象相等比較 (==)
- 嚴格相等比較 (===): 用於 Array.prototype.indexOf,
Array.prototype.lastIndexOf, 和 case-matching - 同值零: 用於 %TypedArray% 和 ArrayBuffer 構造函數、以及Map和Set操作, 並將用於 ES2016/ES7 中的String.prototype.includes
- 同值: 用於所有其他地方
JavaScript提供三種不同的值比較操作:
- 嚴格相等 (“triple equals” 或 “identity”),使用 === ,
- 寬鬆相等 (“double equals”) ,使用 ==
- 以及 Object.is (ECMAScript 2015/ ES6 新特性)
選擇使用哪個操作取決於你需要什麼樣的比較。
簡而言之,在比較兩件事情時,雙等號將執行類型轉換; 三等號將進行相同的比較,而不進行類型轉換 (如果類型不同, 只是總會返回 false ); 而Object.is的行為方式與三等號相同,但是對於NaN和-0和+0進行特殊處理,所以最後兩個不相同,而Object.is(NaN,NaN)將為 true。(通常使用雙等號或三等號將NaN與NaN進行比較,結果為false,因為IEEE 754如是說.) 請注意,所有這些之間的區別都與其處理原語有關; 這三個運算符的原語中,沒有一個會比較兩個變量是否結構上概念類似。對於任意兩個不同的非原始對象,即便他們有相同的結構, 以上三個運算符都會計算得到 false 。

嚴格相等 ===
全等操作符比較兩個值是否相等,兩個被比較的值在比較前都不進行隱式轉換。如果兩個被比較的值具有不同的類型,這兩個值是不全等的。否則,如果兩個被比較的值類型相同,值也相同,並且都不是 number 類型時,兩個值全等。最後,如果兩個值都是 number 類型,當兩個都不是 NaN,並且數值相同,或是兩個值分別為 +0 和 -0 時,兩個值被認為是全等的。

在日常中使用全等操作符幾乎總是正確的選擇。對於除了數值之外的值,全等操作符使用明確的語義進行比較:一個值只與自身全等。對於數值,全等操作符使用略加修改的語義來處理兩個特殊情況:第一個情況是,浮點數 0 是不分正負的。區分 +0 和 -0 在解決一些特定的數學問題時是必要的,但是大部分境況下我們並不用關心。全等操作符認為這兩個值是全等的。第二個情況是,浮點數包含了 NaN 值,用來表示某些定義不明確的數學問題的解,例如:正無窮加負無窮。全等操作符認為 NaN 與其他任何值都不全等,包括它自己。(等式 (x !== x) 成立的唯一情況是 x 的值為 NaN)。
非嚴格相等
相等操作符比較兩個值是否相等,在比較前將兩個被比較的值轉換為相同類型。在轉換後(等式的一邊或兩邊都可能被轉換),最終的比較方式等同於全等操作符 === 的比較方式。 相等操作符滿足交換律。
相等操作符對於不同類型的值,進行的比較如下圖所示:

在上面的表格中,ToNumber(A) 嘗試在比較前將參數 A 轉換為數字,這與 +A(單目運算符+)的效果相同。通過嘗試依次調用 A 的A.toString 和 A.valueOf 方法,將參數 A 轉換為原始值(Primitive)。
一般而言,根據 ECMAScript 規範,所有的對象都與 undefined 和 null 不相等。但是大部分瀏覽器允許非常窄的一類對象(即,所有頁面中的 document.all 對象),在某些情況下,充當效仿 undefined 的角色。相等操作符就是在這樣的一個背景下。因此,IsFalsy(A) 方法的值為 true ,當且僅當 A 效仿 undefined。在其他所有情況下,一個對象都不會等於 undefined 或 null。

有些開發者認為,最好永遠都不要使用相等操作符。全等操作符的結果更容易預測,並且因為沒有隱式轉換,全等比較的操作會更快。
同值相等
同值相等解決了最後一個用例:確定兩個值是否在任何情況下功能上是相同的。(這個用例演示了里氏替換原則的實例。)當試圖對不可變(immutable)屬性修改時發生出現的情況:

Object.defineProperty 在試圖修改不可變屬性時,如果這個屬性確實被修改了則會拋出異常,反之什麼都不會發生。例如如果 v 是 -0 ,那麼沒有發生任何變化,所以也不會拋出任何異常。但如果 v 是 +0 ,則會拋出異常。不可變屬性和新設定的值使用 same-value 相等比較。同值相等由 Object.is 方法提供。
零值相等
與同值相等類似,不過會認為 +0 與 -0 相等。
理解相等比較的模型
在 ES2015 以前,你可能會說雙等和三等是“擴展”的關係。比如有人會說雙等是三等的擴展版,因為他處理三等所做的,還做了類型轉換。例如 6 == “6” 。反之另一些人可能會說三等是雙等的擴展,因為他還要求兩個參數的類型相同,所以增加了更多的限制。怎樣理解取決於你怎樣看待這個問題。
但是這種比較的方式沒辦法把 ES2015 的 Object.is 排列到其中。因為 Object.is 並不比雙等更寬鬆,也並不比三等更嚴格,當然也不是在他們中間。從下表中可以看出,這是由於 Object.is 處理 NaN 的不同。注意假如 Object.is(NaN, NaN) 被計算成 false ,我們就可以說他比三等更為嚴格,因為他可以區分 -0 和 +0 。但是對 NaN 的處理表明,這是不對的。 Object.is 應該被認為是有其特殊的用途,而不應說他和其他的相等更寬鬆或嚴格。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/269629.html