肯定兩個變量是否相等是編程中的一個很是重要的操做。 在比較字符串、數值和布爾值的相等性時,問題還比較簡單。但在涉及到對象的比較時,問題就變得複雜了。最先的 ECMAScript 中的相等和不等 操做符會在執行比較以前,先將對象轉換成類似的類型。後來,有人提出了這種轉換究竟是否合理的質疑。 最後,ECMAScript 的解決方案就是提供兩組操做符: 相等和不相等——先轉換再比較,全等和不全等——僅比較而不轉換。 此處咱們只對相等作一些討論。
"==" 相等 時的隱式轉換編程
對於 "==" 操做符,一般都會先隱式轉換(強制轉換),而後再比較它們的相等性。
若是一個操做數是字符串,另外一個操做數是數值,在比較相等性以前先將字符串轉換爲數值;
字符串轉換爲數值:數組
(1)數字類型的字符串,會被轉成對應十進制的數值; (2)空字符串會轉換成0; (3)其他的全都會轉換爲NaN;(NaN 與任何值都不相等,包括自身)
下面能夠經過一個簡單的例子來看一下 JS 底層的轉換規則。code
// 根據隱式轉換規則第三條 調用對象的 valueOf 方法 [].valueOf() // [] // 這時就變成 [] == false ,又回到原來的狀況,這時JS底層又是怎麼處理的呢? // 其實 JS 的底層在調用 valueOf 獲得的返回結果若是不是原始值時,就會調用對象的 toString 方法將對象轉換成字符串。對於這個過程咱們能夠經過一下的例子來驗證。 [].valueOf() // [] [].toString() // '' //上面是 這兩個方法的 默認行爲,在下面的例子中咱們不改變默認行爲 [].__proto__.valueOf = () => { console.log('valueOf'); return []; } [].__proto__.toString = () => { console.log('toString'); return ''; } [] == false // 運行的結果爲 valueOf toString true // 這樣就驗證了上述的說明 // 咱們還能夠經過下面的方式,從側面在次驗證 JS底層默認的轉換行爲 [].__proto__.valueOf = () => { console.log('valueOf'); return ''; } [].__proto__.toString = () => { console.log('toString'); return ''; } [] == false // valueOf true [].__proto__.valueOf = () => { console.log('valueOf'); return []; } [].__proto__.toString = () => { console.log('toString'); return []; } [] == false // JS 報錯 Uncaught TypeError: Cannot convert object to primitive value
如今咱們能夠來看看例子中 空對象爲何不等於 false?從正常的角度來說,數組就是一個對象,爲何空數組等於 false,而空對象爲何和 false 不相等?對象
//如今咱們能夠參照上面隱式轉換的過程,對空對象手動的執行這個過程,結果以下 ({}).valueOf() // {} ({}).toString() // '[object Object]' // 這時咱們發現 空對象 與 空數組默認行爲的區別了,在 toString 方法上,因爲數組會對繼承自對象的 toString 方法進行重寫,將數組中的每一個元素經過 ',' 連接成一個字符串 // 這時就變成了 '[object Object]' == false // 根據規則第二條,獲得最後結果 false
null == undefined // true NaN == NaN // false NaN != NaN // true false == 0 // true undefined == 0 // true null == 0 // true