iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
自我挑戰組

重新開始 JavaScript系列 第 16

[Day16] 嚴格相等 vs 寬鬆相等

  • 分享至 

  • xImage
  •  

嚴格相等寬鬆相等 是 JavaScript 的比較方法,由以下的運算子來比較結果是否相等,並依結果回傳布林值

  • === 嚴格相等運算子
  • !== 嚴格不相等運算子
  • == 寬鬆相等運算子
  • != 寬鬆不相等運算子
console.log(1 === 1); // true - 嚴格相等
console.log(1 !== 1); // false - 嚴格不相等

console.log(1 == 1); // true - 寬鬆相等
console.log(1 != 1); // false - 寬鬆不相等

嚴格相等/不相等

嚴格相等會比較 ===!== 運算子左右兩邊運算元的 型別,來判定結果,最後依照結果回傳布林值

console.log(1 === 1); // true
console.log(1 === '1'); // false

console.log(1 !== 1); // false
console.log(1 !== '1'); // true

嚴格相等的例外

NaN

NaN (Not a Number) - 意思為 "不是一個數值"

NaNNaN 做比較,嚴格相等及寬鬆相等皆會回傳 false

console.log(NaN === NaN); // false

console.log(NaN == NaN); // false

+0 與 -0

-0+0 雖然值不同,但比較結果為 true

console.log( -0 === +0); // true
console.log( -0 == +0); // true

// 其他數值範例
console.log( -1 === +1); // false
console.log( -1 == +1); // false

寬鬆相等/不相等

寬鬆相等會因做比較的兩者型別不同,而做 隱含轉型 - 先轉換成相同型別再做比較,但並非所有比較都會發生,是有其規則的

以下為寬鬆相等的運作表 (MDN - 相等比較):

寬鬆相等以 ==!= 運算子以及左右兩邊運算元組合而成,先依照規則轉型,再與 做比較,最後依照結果回傳布林值

console.log(1 == 1); // true
console.log(1 == '1'); // true

console.log(1 != 1); // false
console.log(1 != '1'); // false

寬鬆相等的規則

布林與字串會轉為數字型別

以下為 布林型別字串型別 在比較時,會先轉換為 數字型別 的範例:

1. 字串與數字 比較

範例 1-1

字串型別 會先轉換成 數字型別,再與 數字型別 相比較

console.log('1' == 1); // true

console.log(Number('1')); // 1 - 數字型別

Number()String() 為型別包裹器,想知道更多可看 Kuro - 基本型別包裹器

範例 1-2

字串 0x11 與數值做比較,會先轉為數字型別 17

console.log(17 == '0x11'); // true

0x11 為十六進位,轉為十進位為 17

console.log(Number(0x11)); // 17

維基百科 - 十六進位

2. 布林與數字比較

布林型別 會先轉換成 數字型別,再與 數字型別 做比較

console.log(Number(true)); // 1 - 數字型別
console.log(Number(false)); // 0 - 數字型別

// 肯定
console.log(true == 1); // true
console.log(false == 1); // false

// 否定
console.log(true != 1); // false
console.log(false != 1); // true

3. 字串與布林比較

範例 3-1

布林型別字串型別 相比較時,兩者都會先轉成 數字型別 再做比較

// 布林轉數值
console.log(Number(true)); // 1 - 數值
console.log(Number(false)); // 0 - 數值

// 字串轉數值
console.log(Number('1')); // 1
console.log(Number('0')); // 0

// 肯定
console.log(true == '1'); // true
console.log(false == '0'); // true

// 否定
console.log(true != '1'); // false
console.log(false != '0'); // false
範例 3-2
  • !00 會先轉換為 布林值 false
  • !false 再轉換為 布林值 true
  • 布林值 true字串 1 相比較則兩者都會先轉換為數值,因此結果為相等
console.log('1' == !0); // true

console.log(!0); // true
範例 3-3

需要注意的是 字串 true字串 false 轉換成數值時會轉成 NaN

// 布林轉數值
console.log(Number(true)); // 1 - 數值
console.log(Number(false)); // 0 - 數值

// 字串 true、字串 false 轉數值
console.log(Number('true')); // NaN
console.log(Number('false')); // NaN

console.log(true == 'true'); // false
console.log(false == 'false'); // false

Null 與 Undefined 不會轉為數字型別

NullUndefined 比較時,不會轉為數字型別

NullUndefined 比較時只要看對方是否是 NullUndefined 型別,否則結果皆為 false

範例1

雖然用 Number(null) 可得出 數值 0,但因 NullUndefined 不會轉為數字型別比較,此例中得出結果為 false

console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN

console.log(null == 0); // false

範例2

在寬鬆相等下 NullUndefined 比較結果為 true

console.log(null == undefined); // true
console.log(null === undefined); // false

物件的比較

當物件與非物件做比較時,會使用包裹物件做轉換,可參考上面寬鬆相等運作圖表 ToPrimitive(),它會透過 .toString().valueOf() 方法轉換後再做比較,而物件與物件則是比較所參考的物件,而非它們的值

{} 物件[] 陣列 皆是屬於物件型別

1. 物件與數值比較

此例中 陣列 [10] 使用包裹物件方式先轉換為原始型別,再做比較

console.log(10 == [10]); // true

2. 物件與字串比較

當物件與字串做比較,物件會先使用 .toString() 轉換物件

範例2-1

陣列 ['A'] 會先轉換為字串再與字串做比較

console.log(['A'].toString()); // A

console.log('A' == ['A']); // true
範例2-2

物件 {A: 'A'} 轉為字串會顯示 [object Object],所以會與 字串 [object Object] 相等

console.log([{A: 'A'}].toString()); // [object Object] - 字串型別

console.log('[object Object]' == {A: 'A'}); // true

3. 物件與布林比較

物件型別布林型別 做比較時,物件型別會透過包裹物件做轉換,布林型別則會轉為數字型別,再互相做比較

console.log([0] == false); // true

4. 物件與 Null、Undefined 比較

NullUndefined 比較時只要看對方是否是 NullUndefined 型別,否則結果皆為 false

console.log(['null'] == null); // false
console.log(['undefined'] == undefined); // false

5. 物件與物件比較

物件與物件在相比時,比較的不是裡面的值,是兩者的參考位置,所以當物件與物件比較結果為 false,主因是兩個的參考物件不同

範例5-1

雖然以下範例的值相同,但因參考物件不同,所以比較結果為 false

console.log({} == {}); // false

console.log([] == []); // false
範例5-2

變數 b 所取得的是 變數 a 的參考位置,兩者指向同個物件,所參考物件相同,所以 變數 a變數 b 比較為 true

// 物件{} 範例
var a = {};
var b = a;
console.log(a == b); // true
console.log(a === b); // true
// 陣列[] 範例
var a = [];
var b = a;
console.log(a == b); // true
console.log(a === b); // true

小測驗

console.log(0 == false); // number == number => true
console.log(0 == '0'); // number == number => true
console.log(0 == NaN); // 看對方是否是Null與Undefined => false
console.log(0 == undefined); // 看對方是否是 Null 與 Undefined => false

console.log('' == 0); // number == number => true
console.log('0' == ''); // string == string => false
console.log('' == false); // number == number => true
console.log('' == NaN); // 看對方是否是 Null 與 Undefined => false
console.log('' == undefined); // 看對方是否是 Null 與 Undefined => false

console.log(null == undefined); // 看對方是否是 Null 與 Undefined => true
console.log(null == false); // 看對方是否是 Null 與 Undefined => false
console.log(undefined == false); // 看對方是否是 Null 與 Undefined => false
console.log(null == [null]); // 看對方是否是 Null 與 Undefined => false
console.log(undefined == [undefined]); // 看對方是否是 Null 與 Undefined=>false

console.log([] == 0); // 物件轉字串再轉數值,number == number => true
console.log({} == 0); // [object, object] == 0 => false
console.log([] == ''); // 物件轉字串,string == string => true
console.log({} == ''); // 物件轉字串,[object, object] == string => false
console.log([] == false); // 物件轉數值,布林轉數值,number == number => true
console.log({} == false); // 布林轉數值,[object, object] == number => false

參考文獻

六角學院 - JavaScript 核心篇

MDN - 相等比較


上一篇
[Day15] 優先性與相依性
下一篇
[Day17] 強制轉型
系列文
重新開始 JavaScript32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言