-
instanceof 是什么?
instanceof 是用来判断左侧对象是否是右侧构造函数的实例化对象,或则说左侧对象能否通过其隐式原型 **[[proto]]**在原型链上一层层向上查找到右侧函数的原型对象,即函数原型对象出现在实例对象的原型链上就返回 true。
通俗的理解: 右侧是不是左侧的爸爸、爷爷、祖宗,只要左侧对象继承自右侧函数就为 true -
instanceof 使用方式:
object instanceof 构造函数, 它有两个必传参数,左侧必须为对象类型,右侧必须为函数类型。返回值为 Boolean 类型。
注:js中万物皆对象,可能会误导大家出现这种写法:'str' instanceof String
,返回值为false,因为 ‘str’ 就是简单的字符串,它和通过String构造函数(new String('str')
)创造出来的字符串是有区别的,可自行在控制台打印出来看,其值会封装成String对象类型的字符串,同理new Number(3) instanceof Number, new Boolean(true) instanceof Boolean
……等等返回值为true。
数组 则可以直接这样写:
[1,2] instanceof Array // true
函数
function test () {}
test instanceof Function // true
总结如下:
基本数据类型只有通过对应类型构造函数创建出来成对象形式,才会是对应类型构造函数实例(true),直接写基本数据类型值则不是(false),毕竟上面有说到instanceof是用来判断左侧是不是右侧的实例对象,你连对象类型都不是怎么可能为true呢;引用类型可以直接作为左侧实例对象继承自右侧构造函数,返回值为true,如上面数组。
手撕 instanceof
上面有讲到其判断的原理是:通过左侧对象的隐式原型属性 __ proto __ 在原型链上向上一层层查找,找到右侧构造函数的原型对象属性 prototype 就返回 true。明白这一点也就很容易写出自己的 instanceof,注:需要借助循环来实现。
function myInstanceof(obj, func) {
if(!['function', 'object'].includes(typeof obj) || obj === null) {
// 基本数据类型直接返回false,因为不满足instanceof的左侧参数是对象或者说引用类型
return false
}
let proto = obj.__proto__, prototype = func.prototype
while(proto !== prototype) {
// obj.__proto__不等于时,继续通过__proto__向上层查找
// 当找到原型链尽头.__proto__=null 时还未找到,就返回false
proto = proto.__proto__
if(proto === null){
return false
}
}
// obj.__proto__ 等于 prototype = 时,不会进入上面循环,返回true
// 不等进入上面循环,找到相等时会跳出循环,走到这里返回true
return true
}