Javascript 隱式轉換

肯定兩個變量是否相等是編程中的一個很是重要的操做。
在比較字符串、數值和布爾值的相等性時,問題還比較簡單。但在涉及到對象的比較時,問題就變得複雜了。最先的 ECMAScript 中的相等和不等 操做符會在執行比較以前,先將對象轉換成類似的類型。後來,有人提出了這種轉換究竟是否合理的質疑。
最後,ECMAScript 的解決方案就是提供兩組操做符:
    相等和不相等——先轉換再比較,全等和不全等——僅比較而不轉換。
此處咱們只對相等作一些討論。

"==" 相等 時的隱式轉換編程

對於 "==" 操做符,一般都會先隱式轉換(強制轉換),而後再比較它們的相等性。

隱式轉換規則:

  1. 若是有一個操做數是布爾值,則在比較相等性以前先將其轉換爲數值——false 轉換爲 0,而true轉換爲 1;
  2. 若是一個操做數是字符串,另外一個操做數是數值,在比較相等性以前先將字符串轉換爲數值;
    字符串轉換爲數值:數組

    (1)數字類型的字符串,會被轉成對應十進制的數值;
       (2)空字符串會轉換成0;
       (3)其他的全都會轉換爲NaN;(NaN 與任何值都不相等,包括自身)
  3. 若是一個操做數是對象,另外一個操做數不是,則調用對象的 valueOf()方法,用獲得的基本類型值按照前面的規則進行比較;

下面能夠經過一個簡單的例子來看一下 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

隱式轉換的特殊規則:

  1. null 和 undefined 是相等的。
  2. 要比較相等性以前,不能將 null 和 undefined 轉換成其餘任何值。
  3. 若是有一個操做數是 NaN,則相等操做符返回 false,而不相等操做符返回 true。
  4. 若是兩個操做數都是對象,則比較它們是否是同一個對象。(比較引用類型的地址是否相同)
null == undefined  // true
    NaN == NaN         // false
    NaN != NaN         // true
    false == 0         // true
    undefined == 0     // true
    null == 0          // true
相關文章
相關標籤/搜索