1. 程式人生 > 前端設計 >一次弄懂Javascript隱式轉換

一次弄懂Javascript隱式轉換

四種轉換總覽

ToPrimitive

作用

將物件型別轉換為原始型別

語法

ToPrimitive(obj,type)

type不同值的說明

type為string:

  1.先呼叫obj的toString方法,如果為原始值,則return,否則進行第2步
  2.呼叫obj的valueOf方法,如果為原始值,則return,否則進行第3步
  3.丟擲TypeError 異常
複製程式碼

type為number:

  1.先呼叫obj的valueOf方法,如果為原始值,則return,否則進行第2步
  2.呼叫obj的toString方法,如果為原始值,則return,否則第3步
  3.丟擲TypeError 異常
複製程式碼

type引數為空

  1.該物件為Date,則type被設定為String
  2.否則,type被設定為Number
複製程式碼

ToPrimitive總結

ToPrimitive轉成何種原始型別,取決於type,type引數可選。
若指定,則按照指定型別轉換。
若不指定,預設根據實用情況分兩種情況,Date為string,其餘物件為number。
複製程式碼

ToString

將其他型別轉換為字串型別

規則(文字)

null:轉為"null"
undefined:轉為"undefined"
布林型別:true和false分別被轉為"true"和"false"
數字型別:轉為數字的字串形式,如10轉為"10"
陣列:轉為以","連線的字串,空陣列[]轉為空字串,陣列中的null或undefined,會被當做空字串處理
普通物件:轉為字串相當於直接使用Object.prototype.toString(),返回"[object Object]"
複製程式碼

規則(表格)

ToNumber

將其他型別轉換為數字型別

null: 轉為0 undefined:轉為NaN 字串:如果是純數字形式,則轉為對應的數字,空字元轉為0,否則一律按轉換失敗處理,轉為NaN 布林:true和false被轉為1和0 陣列:陣列先被轉為原始型別,然後在根據轉換後的原始型別按照上面的規則處理 物件:同陣列的處理方式 複製程式碼

規則(表格)

ToBoolean

將其他型別轉換為布林型別

null、undefined、0、NaN、””轉為false 其餘轉為 true 複製程式碼

規則(表格)

==運算子規則

比較運算 x==y,其中 x 和 y 是值,返回 true 或者 false。這樣的比較按如下方式進行
1、若 Type(x) 與 Type(y) 相同, 則
    1* 若 Type(x) 為 Undefined, 返回 true。
    2* 若 Type(x) 為 Null, 返回 true。
    3* 若 Type(x) 為 Number, 則
        (1)、若 x 為 NaN, 返回 false。
        (2)、若 y 為 NaN, 返回 false。
        (3)、若 x 與 y 為相等數值, 返回 true。
        (4)、若 x 為 +0 且 y 為 −0, 返回 true。
        (5)、若 x 為 −0 且 y 為 +0, 返回 true。
        (6)、返回 false。
    4* 若 Type(x) 為 String,則當 x 和 y 為完全相同的字元序列(長度相等且相同字元在相同位置)時返回 true。 否則, 返回 false。
    5* 若 Type(x) 為 Boolean,當 x 和 y 為同為 true 或者同為 false 時返回 true。 否則, 返回 false。
    6*  當 x 和 y 為引用同一物件時返回 true。否則,返回 false。
2、若 x 為 null 且 y 為 undefined, 返回 true。
3、若 x 為 undefined 且 y 為 null, 返回 true。
4、若 Type(x) 為 Number 且 Type(y) 為 String,返回比較 x == ToNumber(y) 的結果。
5、若 Type(x) 為 String 且 Type(y) 為 Number,返回比較 ToNumber(x) == y 的結果。
6、若 Type(x) 為 Boolean, 返回比較 ToNumber(x) == y 的結果。
7、若 Type(y) 為 Boolean, 返回比較 x == ToNumber(y) 的結果。
8、若 Type(x) 為 String 或 Number,且 Type(y) 為 Object,返回比較 x == ToPrimitive(y) 的結果。
9、若 Type(x) 為 Object 且 Type(y) 為 String 或 Number, 返回比較 ToPrimitive(x) == y 的結果。
10、返回 false。
複製程式碼

例題解析

a 為什麼值時,控制檯能輸出Hello world?

a = ? // 
if(a == 1 && a == 2 && a == 3){
  console.log("Hello world")
}
複製程式碼

解法1

利用物件在和原始型別的值比較是預設呼叫ToPrimitive方法裡的ValueOf方法

    var a = {
        i: 1,        valueOf() {
            return this.i++;
        }
    }
    if (a == 1 && a == 2 && a == 3) {
        console.log("Hello world");
    }
複製程式碼
1、在判斷a == 1時,因為a為非原始型別,所以需要先呼叫ToPrimitive方法,呼叫valueOf方法。
2、返回this.i值為1,並將i自加1,返回的1與等式右邊的1進行比較返回true。
3、後面的操作同理
複製程式碼

解法2

利用物件在和原始型別的值比較是預設呼叫ToPrimitive方法裡的ToString方法

return this.i++;
        }
    }
    if (a == 1 && a == 2 && a == 3) {
        console.log("Hello world");
    }
複製程式碼
 1、在判斷a == 1時,因為a為非原始型別,所以需要先呼叫ToPrimitive方法,呼叫valueOf方法,返回自身
 2、繼續呼叫toString方法,返回this.i的值為1,並將i自加1,返回的1與等式右邊的1進行比較返回true。
 3、後面的操作同理
複製程式碼

解法3

利用物件在和原始型別的值比較是預設呼叫ToPrimitive方法裡的ToString方法時隱式呼叫join方法

    var a = [1,2,3];
    a.join = a.shift;
    if (a == 1 && a == 2 && a == 3) {
        console.log("Hello world");
    }
複製程式碼
1、在判斷a == 1時,因為a為非原始型別,所以需要先呼叫ToPrimitive方法,呼叫valueOf方法,返回自身
2、繼續呼叫toString方法,toString方法預設呼叫join方法
3、而物件a上的join方法被重寫,變成shift方法,因此執行shift方法返回被刪除的1,陣列變成[2,3]
4、後面的操作同理
複製程式碼

其他解法

  var val = 0;
  Object.defineProperty(window,'a',{
     get: function() {
          return ++val;
    }
  });
  // ---------------------------------
  let a={
      reg: /\d/g,      valueOf(){
          return this.reg.exec(123)[0]
      }
  }
複製程式碼
最後兩個解法不屬於隱式轉換,所以不再展開
複製程式碼

課後習題

  null >0 // false
  null == 0// false
  null >= 0 // true
  [] == ![] // true 
  [] == 0 // true 
  [2]== 2 // true 
  ['0'] == false // true 
  '0' == false // true 
  [] == false // true 
  [null] == 0 // true 
  null == 0 // false 
  [null] == false // true 
  null == false // false 
  [undefined] == false // true 
  undefined == false // false
複製程式碼