JS中的instanceof

201 阅读2分钟

instanceof instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

语法:

object instanceof constructor

object:某个实例对象 constructor:某个构造函数

用来检测 constructor.prototype 是否存在于参数 object 的原型链上。

举例

// 定义构造函数
function C () {}
function D () {}
var o = new C()
console.log(o instanceof C, o.__proto__ === C.prototype) // true,true C.prototype 在 o 的原型链上
console.log(o instanceof D, o.__proto__ === D.prototype) // false,false D.prototype 不在 o 的原型链上
console.log(o instanceof Object, o.__proto__.__proto__ === Object.prototype) // true true
C.prototype = {}
var o2 = new C()
console.log(o2 instanceof C) // true
console.log(o instanceof C) // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.
D.prototype = new C() // 继承
var o3 = new D()
console.log(o3 instanceof D) // true
console.log(o3 instanceof C) // true 因为 C.prototype 现在在 o3 的原型链上

一些容易出错的点

var simpleStr = "This is a simple string"; 
var myString  = new String();
var newStr    = new String("String created with constructor");
var myDate    = new Date();
var myObj     = {};
var myNonObj  = Object.create(null);
​
simpleStr instanceof String; // 返回 false, simpleStr并不是对象
myString  instanceof String; // 返回 true
newStr    instanceof String; // 返回 true
myString  instanceof Object; // 返回 true
​
myObj instanceof Object;    // 返回 true, 尽管原型没有定义
({})  instanceof Object;    // 返回 true, 同上
myNonObj instanceof Object; // 返回 false, 一种创建非 Object 实例的对象的方法
​
myString instanceof Date; // 返回 false
​
myDate instanceof Date;     // 返回 true
myDate instanceof Object;   // 返回 true
myDate instanceof String;   // 返回 false

instanceof能否判断基本数据类型? 能。比如下面这种方式:

class PrimitiveNumber {
  static [Symbol.hasInstance](x) {
    return typeof x === 'number'
  }
}
console.log(111 instanceof PrimitiveNumber) // true

其实就是自定义instanceof行为的一种方式,这里将原有的instanceof方法重定义,换成了typeof,因此能够判断基本数据类型。

手动实现一下instanceof的功能 核心: 原型链的向上查找。

function myInstanceof (left, right) {
    // 基本数据类型直接返回false
    if (typeof left !== 'object' || left === null) return false
    // getProtypeOf是Object对象自带的一个方法,能够拿到参数的原型对象
    let proto = Object.getPrototypeOf(left)
    while (true) {
        // 查找到尽头,还没找到
        if (proto == null) return false
        // 找到相同的原型对象
        if (proto == right.prototype) return true
        proto = Object.getPrototypeOf(proto)
    }
}

测试:

console.log(myInstanceof("111", String)); //false
console.log(myInstanceof(new String("111"), String));//true