JS中不爲人知的問題: [] == ![]結果爲true,而 {} == !{}卻爲false

console.log( [] == ![] )  // true
console.log( {} == !{} )  // false

在比較字符串、數值和布爾值的相等性時,問題還比較簡單。但在涉及到對象的比較時,問題就變得複雜了。最先的ECMAScript中的相等和不相等操做符會在執行比較以前,先將對象轉換成類似的類型。後來,有人提出了這種轉換究竟是否合理的質疑。最後,ECMAScript的解決方案就是提供兩組操做符:javascript

相等和不相等——先轉換再比較    (==)
全等和不全等——僅比較而不轉換  (===)java

ECMAScript中相等操做符由兩個等於號(==)表示,若是兩個操做數相等,則返回true,這種操做符都會先轉換操做數(一般稱爲強制轉型),而後再比較它們的相等性數組

在轉換不一樣的數據類型時,對於相等和不相等操做符:在JS高程中一書中給出以下的基本轉換規則spa

①、若是有一個操做數是布爾值,則在比較相等性以前先將其轉換爲數值——false轉換爲0,而true轉換爲1;
②、若是一個操做數是字符串,另外一個操做數是數值,在比較相等性以前先將字符串轉換爲數值
③、若是一個操做數是對象,另外一個操做數不是,則調用對象的valueOf()方法,用獲得的基本類型值按照前面的規則進行比較

這兩個操做符在進行比較時則要遵循下列規則。
①、null 和undefined 是相等的
②、要比較相等性以前,不能將null 和 undefined 轉換成其餘任何值
③、若是有一個操做數是NaN,則相等操做符返回 false ,而不相等操做符返回 true。重要提示:即便兩個操做數都是NaN,相等操做符也返回 false了;由於按照規則, NaN 不等於 NaN
④、若是兩個操做數都是對象,則比較它們是否是同一個對象,若是兩個操做數都指向同一個對象,則相等操做符返回 true;不然, 返回falsecode

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21hZ2ljX3hpYW5n,size_16,color_FFFFFF,t_70

這裏說一下題外話:[] 和 {} 都是屬於引用類型,引用類型是存放在堆內存中的,而在棧內存中會有一個或者多個地址來指向這個堆內存相對應的數據。因此在使用 == 操做符的時候,對於引用類型的數據,比較的是地址,而不是真實的值。對象

如今來探討 [] == ! [] 的結果爲何會是true

①、根據運算符優先級 ,! 的優先級是大於 == 的,因此先會執行 ![]blog

!可將變量轉換成boolean類型,null、undefined、NaN以及空字符串('')取反都爲true,其他都爲false。ip

因此 ! [] 運算後的結果就是 false內存

也就是 [] == ! [] 至關於 [] == false字符串

②、根據上面提到的規則(若是有一個操做數是布爾值,則在比較相等性以前先將其轉換爲數值——false轉換爲0,而true轉換爲1),則須要把 false 轉成 0

也就是 [] == ! [] 至關於 [] == false 至關於 [] == 0

③、根據上面提到的規則(若是一個操做數是對象,另外一個操做數不是,則調用對象的valueOf()方法,用獲得的基本類型值按照前面的規則進行比較,若是對象沒有valueOf()方法,則調用 toString()

而對於空數組,[].toString() ->  '' (返回的是空字符串)

也就是  [] == 0 至關於 '' == 0

④、根據上面提到的規則(若是一個操做數是字符串,另外一個操做數是數值,在比較相等性以前先將字符串轉換爲數值

Number('') -> 返回的是 0

至關於 0 == 0 天然就返回 true了

總結一下:

[] == ! []   ->   [] == false  ->  [] == 0  ->   '' == 0   ->  0 == 0   ->  true

那麼對於 {} == !{} 也是同理的

關鍵在於  {}.toString() ->  NaN(返回的是NaN)

根據上面的規則(若是有一個操做數是NaN,則相等操做符返回 false

總結一下:

{} == ! {}   ->   {} == false  ->  {} == 0  ->   NaN == 0    ->  false

那麼相信你們對下面的兩道題就信手拈來了

console.log( [] == !{} ) // true
console.log( {} == ![] ) // false

本文屬於magic_xiang原創,轉載需註明來源

相關文章
相關標籤/搜索