typeof & instanceof 原理

949 阅读2分钟

typeof 的八种数据类型

typeof可判断类型比较有限,它的输出值只有八种,即用 typeof 判断一个变量,得到的结果只会是以下八种类型中的一种

// 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 诞生之初就只有六种类型判断。

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 都为 true

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 类型。

000 对象
010 浮点数
100 字符串
110 布尔值
1   整数

null:所有码都是0
undefined:用 -2^30 表示
可以用 instanceof 判断 null 类型嘛?

答案依然是 NO,因为 null 根本没有 __proto__ 属性,所以用 instanceof 去检测永远都不会返回 true

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 可以判断所有类型

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 的理解应该非常到位了。

Object instanceof Object
Function instanceof Function
Function instanceof Object
Object instanceof Function