請說明 JavaScript 中 == 和 === 的差異為何?
==
是鬆散比較運算子、===
是嚴格比較運算子,兩者最大的不同:==
是當等號兩邊 values 的型別不同時,會強制轉換資料型別與值,而 ===
不會。
===
嚴格比較
必須等號雙邊的值與型別一致,才會回傳 true
,如果型別不同,即使值相同,也會回傳 false
。
==
鬆散比較
==
會當等號運算子兩邊值的型別不同時,會在將兩邊的值進行比較之前,強制轉換型別和值,再進行比較。
常見的強制轉換規則
Boolean
,String
,Number
型別比較時會轉換為數字。true
會轉換為1
,false
會轉換為0
。null == undefined
回傳true
,因為它們被認為是"相等的",即使型別不同。null
和undefined
與其他任何值比較(如數字、布林值、字串等)時,會回傳false
。- 當一個物件與一個原始值進行比較時,會嘗試使用
valueOf
方法將物件轉換為一個原始值。 - 當一個陣列與一個非陣列值進行比較時,會使用陣列的
toString
方法轉換成字串。
Object.is()
比 ===
更嚴格的比較,會檢查傳入兩個的值是否為相同值,然後會回傳 Boolean 。
與 ===
不同的是:
===
會將-0
和+0
視為相等,但Object.is()
視為不同值。===
會將NaN
和NaN
視為不同相等,但Object.is()
視為相等。
實例練習1
// This is a JavaScript Quiz from BFE.dev
console.log(0 == false);
console.log("" == false);
console.log([] == false);
console.log(undefined == false);
console.log(null == false);
console.log("1" == true);
console.log(1n == true);
console.log(" 1 " == true);
解題1
console.log(0 == false);
true
,因為 false
會被強制型別轉換成 0
,0 == 0
值相等。
console.log("" == false);
true
,因為空字串跟 false
會被強制型別轉換成 0
。
console.log([] == false);
true
,因為空陣列會先被轉成空字串,空字串會再轉成 0
,false
會被轉成 0
,0 == 0
值相等。
console.log(undefined == false);
false
,因為 undefined
只會與 null
寬鬆相等。
console.log(null == false);
false
,因為 null
只會與 undefined
寬鬆相等。
console.log("1" == true);
true
,因為 "1"
會被轉成 1
,true
會被轉成 1
,1 == 1
值相等。
console.log(1n == true);
true
,因為 1n
會從 BigInt 轉成 1
,true
會被轉成 1
,1 == 1
值相等。
console.log(" 1 " == true);
true
,因為 " 1 "
會轉成 1
,true 會被轉成 1
,1 == 1
值相等。
實例練習2
// This is a JavaScript Quiz from BFE.dev
console.log(0 == "0");
console.log(0 === "0");
console.log(Object.is(0, "0"));
console.log(0 == 0);
console.log(0 === 0);
console.log(Object.is(0, 0));
console.log(0 == -0);
console.log(0 === -0);
console.log(Object.is(0, -0));
console.log(NaN == NaN);
console.log(NaN === NaN);
console.log(Object.is(NaN, NaN));
console.log(0 == false);
console.log(0 === false);
console.log(Object.is(0, false));
解題2
console.log(0 == "0");
true
,鬆散比較會強制轉換 "0"
的型別為 0
, 0 == 0
值相等。
console.log(0 === "0");
false
,因嚴 格比較兩邊的型別需相同。
console.log(Object.is(0, "0"));
false
,因 Object.is
進行同值嚴格比較,兩個型別不同。
console.log(0 == 0);
true
,兩邊值相同。
console.log(0 === 0);
true
,兩邊值相同。
console.log(Object.is(0, 0));
true
,兩邊值相同。
console.log(0 == -0);
true
,0
跟 -0
在 JavaScript 中鬆散比較被認為是相等的。
console.log(0 === -0);
true
,0
跟 -0
在 JavaScript 中嚴格比較被認為是相等的。
console.log(Object.is(0, -0));
false
,因 Object.is
進行同值嚴格比較認為 0
和 -0
是不相等的。
console.log(NaN == NaN);
false
,在 JavaScript 中,NaN(Not-a-Number)
與任何值都不相等,包括它自己。
console.log(NaN === NaN);
false
,在 JavaScript 中,NaN(Not-a-Number)
與任何值都不相等,包括它自己。
console.log(Object.is(NaN, NaN));
true
,因 Object.is
認為 NaN
與 NaN
是相等的。
console.log(0 == false);
true
,因為鬆散比較 false
會轉型為 0
, 0 == 0
值相等。
console.log(0 === false);
false
,因嚴格比較兩邊的型別需相同。
console.log(Object.is(0, false));
false
,因兩個值的類型不同。
實例練習3
// This is a JavaScript Quiz from BFE.dev
console.log([1] == 1);
console.log([1] == "1");
console.log(["1"] == "1");
console.log(["1"] == 1);
console.log([1] == ["1"]);
console.log(new Boolean(true) == 1);
console.log(new Boolean(true) == new Boolean(true));
console.log(Boolean(true) == "1");
console.log(Boolean(false) == [0]);
console.log(new Boolean(true) == "1");
console.log(new Boolean(false) == [0]);
console.log(null == undefined);
解題3
console.log([1] == 1);
true
,在鬆散比較下,當一個陣列與一個非陣列值進行比較時,會使用陣列的 toString
方法轉換成字串,[1]
會被轉換為 "1"
,"1"
再轉成 1
,1 == 1
值相等。
console.log([1] == "1");
true
,在鬆散比較下 [1]
會轉成"1"
,"1"== "1"
值相等。
console.log(["1"] == "1");
true
,在鬆散比較下 ["1"]
會轉成"1"
,"1"== "1"
值相等。
console.log(["1"] == 1);
true
,在鬆散比較下 ["1"]
會轉成"1"
,,"1"
再轉成 1
,1 == 1
值相等。
console.log([1] == ["1"]);
false
,因為 ["1"]
、[1]
都是陣列,兩個物件的參考的記憶體位置不相同。
console.log(new Boolean(true) == 1);
true
,在鬆散比較下,當一個物件與一個原始值進行比較時,JavaScript 會嘗試使用 valueOf
方法將物件轉換為一個原始值,new Boolean(true)
轉成true
,true
再轉換成1
,1 == 1
值相等。
console.log(new Boolean(true) == new Boolean(true));
false
,因為兩個物件相比較時,會檢查兩個物件的參考的記憶體位置是否相同。
console.log(Boolean(true) == "1");
true
,Boolean(true)
會返回 true
,true
轉為 1
,"1" 轉為 1,1 == 1
值相等。
console.log(Boolean(false) == [0]);
true
,Boolean(false)
會返回 false
,[0]
會轉成 "0"
, false
再轉成 0