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 去检测永远都不会返回 trueui

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
复制代码
相关文章
相关标签/搜索