ES2015中有四種相等算法:
非嚴格相等比較 (==)
嚴格相等比較 (===): 用于?Array.prototype.indexOf,Array.prototype.lastIndexOf,?和case-matching
同值零: 用于%TypedArray%和ArrayBuffer?構(gòu)造函數(shù)、以及Map和Set操作, 并將用于 ES2016/ES7 中的String.prototype.includes
同值: 用于所有其他地方
JavaScript提供三種不同的值比較操作:
嚴格相等 ("triple equals" 或 "identity"),使用?===,
寬松相等 ("double equals")?,使用?==
以及?Object.is?(ECMAScript 2015/ ES6 新特性)
選擇使用哪個操作取決于你需要什么樣的比較。
簡而言之,在比較兩件事情時,雙等號將執(zhí)行類型轉(zhuǎn)換; 三等號將進行相同的比較,而不進行類型轉(zhuǎn)換 (如果類型不同, 只是總會返回 false );??而Object.is的行為方式與三等號相同,但是對于NaN和-0和+0進行特殊處理,所以最后兩個不相同,而Object.is(NaN,NaN)將為true。(通常使用雙等號或三等號將NaN與NaN進行比較,結(jié)果為false,因為IEEE 754如是說.)?請注意,所有這些之間的區(qū)別都與其處理原語有關(guān);?這三個運算符的原語中,沒有一個會比較兩個變量是否結(jié)構(gòu)上概念類似。對于任意兩個不同的非原始對象,即便他們有相同的結(jié)構(gòu), 以上三個運算符都會計算得到 false 。
嚴格相等?===
全等操作符比較兩個值是否相等,兩個被比較的值在比較前都不進行隱式轉(zhuǎn)換。如果兩個被比較的值具有不同的類型,這兩個值是不全等的。否則,如果兩個被比較的值類型相同,值也相同,并且都不是 number 類型時,兩個值全等。最后,如果兩個值都是 number 類型,當(dāng)兩個都不是 NaN,并且數(shù)值相同,或是兩個值分別為 +0 和 -0?時,兩個值被認為是全等的。
var b = false;
console.log(num === num); // true
console.log(obj === obj); // true
console.log(str === str); // true
console.log(num === obj); // false
console.log(num === str); // false
console.log(obj === str); // false
console.log(null === undefined); // false
console.log(obj === null); // false
console.log(obj === undefined); // false
非嚴格相等?==
相等操作符比較兩個值是否相等,在比較前將兩個被比較的值轉(zhuǎn)換為相同類型。在轉(zhuǎn)換后(等式的一邊或兩邊都可能被轉(zhuǎn)換),最終的比較方式等同于全等操作符 === 的比較方式。?相等操作符滿足交換律。
var num = 0;
var obj = new String("0");
var str = "0";
var b = false;
console.log(num == num); // true
console.log(obj == obj); // true
console.log(str == str); // true
console.log(num == obj); // true
console.log(num == str); // true
console.log(obj == str); // true
console.log(null == undefined); // true
// both false, except in rare cases
console.log(obj == null);
console.log(obj == undefined);
同值相等
// 向 Nmuber 構(gòu)造函數(shù)添加一個不可變的屬性 NEGATIVE_ZEROObject.defineProperty(Number,"NEGATIVE_ZERO",{value:-0,writable:false,configurable:false,enumerable:false});functionattemptMutation(v){Object.defineProperty(Number,"NEGATIVE_ZERO",{value:v});}
Object.defineProperty?在試圖修改不可變屬性時,如果這個屬性確實被修改了則會拋出異常,反之什么都不會發(fā)生。例如如果 v 是 -0 ,那么沒有發(fā)生任何變化,所以也不會拋出任何異常。但如果 v 是 +0 ,則會拋出異常。不可變屬性和新設(shè)定的值使用 same-value 相等比較。
零值相等
與同值相等類似,不過會認為 +0 與 -0 相等。
什么時候使用?Object.is?或是三等
總的來說,除了對待NaN的方式,Object.is唯一讓人感興趣的,是當(dāng)你需要一些元編程方案時,它對待0的特殊方式,特別是關(guān)于屬性描述器,即你的工作需要去鏡像Object.defineProperty的一些特性時。如果你的工作不需要這些,那你應(yīng)該避免使用Object.is,使用===來代替。即使你需要比較兩個NaN使其結(jié)果為true,總的來說編寫使用NaN?檢查的特例函數(shù)(用舊版本ECMAScript的isNaN方法)也會比想出一些計算方法讓Object.is不影響不同符號的0的比較更容易些。