instanceof检测对象原型链是否包含构造函数的prototype,通过逐级比对__proto__实现;不适用于原始值、跨iframe场景,此时应使用Array.isArray()或Object.prototype.toString.call()。

instanceof 检测的是对象的原型链上是否**存在构造函数的 prototype 属性所指向的对象**,不是简单比对构造函数名,也不是检查对象“属于哪个类”,而是沿着 __proto__ 链向上查找——这是精准判断的关键。
核心原理:原型链查找
表达式 obj instanceof Constructor 的执行过程如下:
- 从
obj.__proto__开始,逐级向上访问原型(即Object.getPrototypeOf(obj)) - 若某一级原型 ===
Constructor.prototype,返回true - 若查到
null还没匹配,返回false
注意:instanceof 不关心 Constructor 是否真的“创建了”这个对象,只看原型链关系。例如:
console.log(arr instanceof Array); // true
let obj = {};
obj.__proto__ = Array.prototype;
console.log(obj instanceof Array); // true ← 虽然不是 new Array() 创建,但原型链匹配
跨 iframe 场景下失效?用 constructor.name 不可靠
不同 iframe 或 window 中定义的同名构造函数(如 Array)是**不同的引用**,它们的 prototype 对象不相等:
立即学习“Java免费学习笔记(深入)”;
iframe.contentWindow.Array !== Array- 所以
iframeArr instanceof Array返回false,即使它确实是数组 - 此时不能依赖
constructor.name(易被篡改)或instanceof跨域检测
更稳妥的方式是使用 Array.isArray()、Object.prototype.toString.call() 等内置方法做类型识别。
自定义类与继承时的正确用法
确保子类正确设置原型链,instanceof 才能按预期工作:
class Dog extends Animal {}
const dog = new Dog();
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true ← 因为 Dog.prototype.__proto__ === Animal.prototype
console.log(dog instanceof Object); // true ← 所有对象最终继承自 Object
若手动修改原型链(如用 Object.setPrototypeOf()),只要链路完整,instanceof 仍有效;但避免直接赋值 __proto__(非标准且性能差)。
替代方案:何时不该用 instanceof
以下情况建议换更明确的方法:
- 检测原生类型:用
typeof("string"、"function")或Array.isArray() - 跨环境对象识别:统一用
Object.prototype.toString.call(obj)(返回"[object Array]"等) - 判断对象是否具有某行为:用鸭子类型,如
typeof obj.forEach === 'function' - ES6+ 模块中动态构造函数:
instanceof依赖静态引用,运行时构造需配合Symbol.hasInstance自定义逻辑


















