instanceof 和 typeof 的实现原理

769 阅读3分钟

typeof和instanceof

typeof

释义

  • 是一个一元运算符,放在一个运算符之前,运算符可以是任意类型
  • typeof 来判断number, string, object, boolean, function, undefined, symbol 这七种类型
  • 局限性:判断引用类型时候,返回都是object

实现原理机制

  • js在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息
    • 000: 对象
    • 010:浮点数
    • 100: 字符串
    • 110: 布尔
    • 1: 整数
  • 对于undefined和null比较特殊
    • null: 所有机器码均为0,直接被当做对象来看待
    • undefined:用-2^30整数来表述
  • 还有一个判断类型的方法:Object.prototype.toString
    • Object.prototype.toString.call(1) // "[object Number]"

    • Object.prototype.toString.call('hi') // "[object String]"

    • Object.prototype.toString.call({a:'hi'}) // "[object Object]"

    • Object.prototype.toString.call([1,'a']) // "[object Array]"

    • 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(1)) // "[object Symbol]"

instanceof

释义

  • instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的prototype属性,用于判断一个变量是否某个对象的实例
  • 判断规则:instanceof运算符的第一个变量是一个对象,暂称为A;第二个变量一般是个函数,暂称为B。沿着A的_proto_这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,就返回true,如果终点都没有哦重合就返回false

instanceof 操作符的实现原理

  • 根据ECMAScript语言规范,整理了一下代码
function new_instance_of(leftVaule, rightVaule) { 
    let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
    leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
    while (true) {
    	if (leftVaule === null) {
            return false;	
        }
        if (leftVaule === rightProto) {
            return true;	
        } 
        leftVaule = leftVaule.__proto__ 
    }
}
  • 原理就是只要右边变量的prototype在左边变量的原型链上即可。因此,instanceof在查找的过程中会遍历左边变量的原型链,直到找到右边变量的prototype,如果查找失败则会范湖false

    • 示例
    function Foo() {}
    Object instanceof Object // true
    Function instanceof Function // true
    Function instanceof Object // true
    Foo instanceof Foo // false
    Foo instanceof Objet // true
    Foo instanceof Function // true
    
    • Object instanceof Object

      • Object 的 prototype 属性是 Object.prototype, 而由于 Object 本身是一个函数,由 Function 所创建,所以 Object.proto 的值是 Function.prototype,而 Function.prototype 的 proto 属性是 Object.prototype,所以我们可以判断出,Object instanceof Object 的结果是 true 。用代码简单的表示一下
      • Function instanceof Function 和 Function instanceof Object 的运行过程与 Object instanceof Object 类似
      leftValue = Object.__proto__ = Function.prototype;
      rightValue = Object.prototype;
      // 第一次判断
      leftValue != rightValue
      leftValue = Function.prototype.__proto__ = Object.prototype
      // 第二次判断
      leftValue === rightValue
      // 返回 true
      
    • Foo instanceof Foo

      • Foo 函数的 prototype 属性是 Foo.prototype,而 Foo 的 proto 属性是 Function.prototype,由图可知,Foo 的原型链上并没有 Foo.prototype ,因此 Foo instanceof Foo 也就返回 false 。我们用代码简单的表示一下
    leftValue = Foo, rightValue = Foo
    leftValue = Foo.__proto = Function.prototype
    rightValue = Foo.prototype
    // 第一次判断
    leftValue != rightValue
    leftValue = Function.prototype.__proto__ = Object.prototype
    // 第二次判断
    leftValue != rightValue
    leftValue = Object.prototype = null
    // 第三次判断
    leftValue === null
    // 返回 false
    
    • Foo instanceof Object
    leftValue = Foo, rightValue = Object
    leftValue = Foo.__proto__ = Function.prototype
    rightValue = Object.prototype
    // 第一次判断
    leftValue != rightValue
    leftValue = Function.prototype.__proto__ = Object.prototype
    // 第二次判断
    leftValue === rightValue
    // 返回 true
    
    • Foo instanceof Function
    leftValue = Foo, rightValue = Function
    leftValue = Foo.__proto__ = Function.prototype
    rightValue = Function.prototype
    // 第一次判断
    leftValue === rightValue
    // 返回 true
    
  • 主要的作用就是判断一个实例是否属于某种类型

let person = function () {}
let nicole = new person()
nicole instanceof person // true
  • 也可以判断一个实例是否是其父类型或者祖先类型的实例
let person = function () {}
let pro = function () {}
pro.prototype = new person()
let n = new pro()
n instanceof person // true
n instanceof pro // true

参考资料

参考资料2