instanceof 运算符
instanceof 判断右边构造器的 prototype 是否出现在左边对象的原型链上,本质是原型关系判断。
#type / concept
#status / evergreen
#resource / javascript
#resource / ecmascript
[!info] related notes
instanceof 运算符
一句话定义
instanceof 判断的是”右边构造函数的 prototype,是否出现在左边对象的原型链上”——本质是原型链查找,不是底层类型判断。
用法
[] instanceof Array // true
[] instanceof Object // true(原型链上能找到 Object.prototype)
new Date() instanceof Date // true
原理
等价于沿原型链向上查找:
function myInstanceof(obj, Constructor) {
if (obj == null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return false;
}
const prototype = Constructor.prototype;
let proto = Object.getPrototypeOf(obj);
while (proto !== null) {
if (proto === prototype) return true;
proto = Object.getPrototypeOf(proto);
}
return false;
}
继承关系
function Person() {}
const p = new Person();
p instanceof Person // true (p.__proto__ === Person.prototype)
p instanceof Object // true (Person.prototype.__proto__ === Object.prototype)
不适用场景
1. 不能判断原始类型
123 instanceof Number // false
'abc' instanceof String // false
原始值不是对象,不走原型链。
new Number(123) instanceof Number // true(包装对象)
2. 跨 realm / 跨 iframe 失效
不同 iframe 有独立的全局环境和构造函数:
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const iframeArray = iframe.contentWindow.Array();
iframeArray instanceof Array // false
iframeArray instanceof iframe.contentWindow.Array // true
解决方案:用 Array.isArray() 或 Object.prototype.toString.call()。
3. 可被 Symbol.hasInstance 干预
class MyClass {
static [Symbol.hasInstance](obj) {
return obj && obj.flag === true;
}
}
({ flag: true }) instanceof MyClass // true
instanceof 不是绝对客观的底层判断,而是一个可定制协议。
适用场景
- 自定义类实例判断:
err instanceof Error - 同一 realm 内判断构造器关系:
promise instanceof Promise