首發位址
相信剛接觸JS的人都會被他的想等性判斷給整糊塗,看看下面代碼,你能答對幾個?
NaN === NaN // false
NaN == NaN // false
Object.is(NaN, NaN) // true
0 == false // true
1 == true // true
Number(null) === 0 // true
null == 0 // false
Javascript提供了三種不同的值比較操作,分别是嚴格相等、寬松相等、以及Object.is,今天查完資料後做了一下總結,希望下面的内容能夠對大家有所幫助,如果哪些地方有誤的話,也歡迎大家指正。
1. 嚴格相等 x === y判斷邏輯
- 如果x的資料類型和y的資料類型不相同,傳回false;
- 如果x是Number類型
- x是NaN,傳回false
- y是NaN,傳回false
- x的值和y的值相等,傳回true
- x是+0,y是-0,傳回true
- x是-0,y是+0,傳回true
- 否則傳回false
- 其他類型參照SameValueNonNumber(x, y)
- 斷言:x,y不是Number類型;
- 斷言: x,y的資料類型相同;
- x是undefined, y是undefined return true;
- x是null, y是null,return true;
- x是字元串類型,當且僅當x,y字元序列完全相同時(長度相同,每個位置上的字元也相同)傳回true, 否則傳回false;
- 如果x是布爾類型,當x,y都為true或者都為false時傳回true,否則傳回false;
- 如果x是symbol類型,當x,y是相同的symbol值,傳回true,否則傳回false;
- 如果x,y是同一個對象值,傳回true,否則傳回false;
NaN === NaN // false
undefined === undefined // true
null === null // true
undefined === null // false
2. 寬松相等 x == y
- 如果x,y的類型相同,傳回x===y的結果;
- 如果x是null, y是undefined, 傳回true;
- 如果x是undefined, y是null, 傳回true;
- 如果x是數值,y是字元串, 傳回x == ToNumber(y);
- 如果x是字元串,y是數值, 傳回ToNumber(x) == y;
- 如果x是布爾類型, 傳回ToNumber(x)==y 的結果;
- 如果y是布爾類型,傳回 x==ToNumber(y) 的結果;
- 如果x是String或Number或Symbol中的一種并且Type(y)是Object,傳回 x==ToPrimitive(y) 的結果
- 如果Type(x)是Object并且Type(y)是String或Number或Symbol中的一種,傳回 ToPrimitive(x)==y 的結果
- 其他傳回false
12 == '0xc' // true, 0xc是16進制
12 == '12' // true
12 == '12c' // false, 說明ToNumber轉換是用的Number()方法
注意:
Number(null) === 0
但是
null == 0 // false,

2.1 ToNumber将一個值轉換為數值類型
詳情參考數值類型轉換
- 如果是boolean類型, true傳回1,false傳回0;
- 如果是數值,隻是簡單的傳入傳回;
- 如果是null,傳回0
- 如果是undefined, 傳回NaN;
- 如果是字元串,字元串如果隻包含數字,則将其轉換成十進制數;如果是有效的浮點格式,将其轉換成對應的浮點數值;如果是二進制或十六進制将其轉換成對應的十進制數值;
- 如果是對象,調用對象的valueOf()方法,然後依照前面規則轉換,如果valueOf傳回值是NaN,則調用toString()方法,再依照前面的規則轉換傳回的字元串
2.2 ToPrimitive
toPrimitive(A)通過嘗試調用 A 的A.toString() 和 A.valueOf() 方法,将參數 A 轉換為原始值(Primitive);
JS中原始類型有:Number、String、Boolean、Null、Undefined;
不同類型對象的valueOf()方法的傳回值:
對象 | 傳回值 |
---|---|
Array | 傳回數組對象本身。 |
Boolean | 布爾值 |
Date | 存儲的時間是從 1970 年 1 月 1 日午夜開始計的毫秒數 UTC |
Function | 函數本身 |
Number | 數字值 |
Object | 對象本身。這是預設情況, 可以覆寫自定義對象的valueOf方法 |
String | 字元串值 |
// Array:傳回數組對象本身
var array = ["ABC", true, 12, -5];
console.log(array.valueOf() === array); // true
// Date:目前時間距1970年1月1日午夜的毫秒數
var date = new Date(2013, 7, 18, 23, 11, 59, 230);
console.log(date.valueOf()); // 1376838719230
// Number:傳回數字值
var num = 15.26540;
console.log(num.valueOf()); // 15.2654
// 布爾:傳回布爾值true或false
var bool = true;
console.log(bool.valueOf() === bool); // true
// new一個Boolean對象
var newBool = new Boolean(true);
// valueOf()傳回的是true,兩者的值相等
console.log(newBool.valueOf() == newBool); // true
// 但是不全等,兩者類型不相等,前者是boolean類型,後者是object類型
console.log(newBool.valueOf() === newBool); // false
// Function:傳回函數本身
function foo(){}
console.log( foo.valueOf() === foo ); // true
var foo2 = new Function("x", "y", "return x + y;");
console.log( foo2.valueOf() );
/*
ƒ anonymous(x,y
) {
return x + y;
}
*/
// Object:傳回對象本身
var obj = {name: "張三", age: 18};
console.log( obj.valueOf() === obj ); // true
// String:傳回字元串值
var str = "http://www.xyz.com";
console.log( str.valueOf() === str ); // true
// new一個字元串對象
var str2 = new String("http://www.xyz.com");
// 兩者的值相等,但不全等,因為類型不同,前者為string類型,後者為object類型
console.log( str2.valueOf() === str2 ); // false
3.同值相等
同值相等由 Object.is 方法判斷:
- 兩個值都是 undefined
- 兩個值都是 null
- 兩個值都是 true 或者都是 false
- 兩個值是由相同個數的字元按照相同的順序組成的字元串
- 兩個值指向同一個對象
- 兩個值都是數字并且
- 都是正零 +0,
- 或者都是負零 -0,
- 或者都是 NaN
- 都是除零和 NaN 外的其它同一個數字
Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
Object.is(null, null); // true
Object.is(true, 'true') // false
// 特例
Object.is(0, -0); // false
Object.is(0, +0); // true
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
4.零值相等
與同值相等類似,不過會認為 +0 與 -0 相等。
小結
- === 不做類型轉換,當兩邊的數類型不相同時,直接傳回false;目前類型相同且都是數值類型的時候,有一個是NaN,那麼結果就是false, 另外 +0 === -0
- ==運算符,當兩邊操作數類不相同時會做隐式轉換,然後才進行比較,這樣的話就會出現 false == 0, '' == false 等現象, 但是Object.is不會做這種轉換