typeof & instanceof 原理

typeof 的八種數據類型

typeof可判斷類型比較有限,它的輸出值只有八種,即用 typeof 判斷一個變量,獲得的結果只會是如下八種類型中的一種javascript

// es5
typeof ''           // string
typeof 1            // number
typeof true         // boolean
typeof undefined    // undefined
typeof Array        // function
typeof {}           // object

// es6
typeof Symbol()     // symbol

// es10
typeof BigInt(1)    // bigint
複製代碼

typeof 的實現原理

初版 JStypeof 實現以下,在 JS 誕生之初就只有六種類型判斷。java

if (JSVAL_IS_VOID(v)) {    // 判斷是否爲 undefined
    type = JSTYPE_VOID;
} else if (JSVAL_IS_OBJECT(v)) { // 判斷是否爲 object
    obj = JSVAL_TO_OBJECT(v);
    if (obj && (ops = obj->map->ops, ops == &js_ObjectOps) 
      ? (clasp = OBJ_GET_CLASS(cx, obj), clasp->call || clasp == &js_FunctionClass)
      : ops->call != 0) {
        type = JSTYPE_FUNCTION;
    } else {
        type = JSTYPE_OBJECT;     
    }
} else if (JSVAL_IS_NUMBER(v)) { // 判斷是否爲 number
    type = JSTYPE_NUMBER;
} else if (JSVAL_IS_STRING(v)) { // 判斷是否爲 string
    type = JSTYPE_STRING;
} else if (JSVAL_IS_BOOLEAN(v)) { // 判斷是否爲 boolean
    type = JSTYPE_BOOLEAN;
}
複製代碼

數組的判斷

typeof 的輸出值中沒有 array 這一項,因此當須要判斷數組類型時,能夠使用 instanceofinstanceof 會判斷右側表達式是否在左側表達式的原型鏈上,因此下面的兩個 instanceof 都爲 truees6

typeof [1,2]            // object
[1,2] instanceof Array  // true
[1,2] instanceof Object // true
複製代碼

獨樹一幟的 null

能夠用 typeof 判斷 null 類型嘛?

答案是 NO,前面說了,typeof 只有八種類型,其中並無 null 這一類型,若是用 typeof 判斷,會獲得 object 的結果。數組

typeof null             // object
複製代碼
爲何?

由於在 Javascript 底層存儲變量的時候,會在變量的機器碼低位 1-3 位表示類型信息。而 null 的低位 1-3 解析到的爲 000,而000 表示的是 obecjt 類型。bash

000 對象
010 浮點數
100 字符串
110 布爾值
1   整數

null:全部碼都是0
undefined:用 -2^30 表示
複製代碼
能夠用 instanceof 判斷 null 類型嘛?

答案依然是 NO,由於 null 根本沒有 __proto__ 屬性,因此用 instanceof 去檢測永遠都不會返回 truemarkdown

null instanceof Object  // false
null instanceof null    // 報錯
複製代碼
那要怎麼判斷?
  1. 強等,最簡單的判斷方式 === 判斷是不是 null
  2. 經過 Object.prototype.toString 判斷
null === null                           // true
Object.prototype.toString.call(null)    // [object Null]
複製代碼

拓展:Object.prototype.toString 能夠判斷全部類型es5

Object.prototype.toString.call(1)       // [object Number]
Object.prototype.toString.call('')      // [object String]
Object.prototype.toString.call({})      // [object Object]
Object.prototype.toString.call(true)    // [object Boolean]
Object.prototype.toString.call(()=>{})  // [object Function]
Object.prototype.toString.call(null)    // [object Null]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(Symbol)  // [object Symbol]
Object.prototype.toString.call(1n)      // [object BigInt]
複製代碼

instanceof 實現原理

function new_instance_of(leftValue, rightValue) {
    let rightProto = rightValue.prototype;
    leftValue = leftValue.__proto__;
    while(true) {
        if (leftValue === null) {
            return false;
        }
        if (leftValue === rightProto) {
            return true;
        }
        leftValue = leftValue.__proto__
    }
}
複製代碼

課後習題

下面的表達式分別輸出什麼呢?若是所有回答正確,你對原型鏈和 instanceof 的理解應該很是到位了。spa

Object instanceof Object
Function instanceof Function
Function instanceof Object
Object instanceof Function
複製代碼
相關文章
相關標籤/搜索