instanceof 原理及实现
核心记住一句话:用来判断谁是谁的爹
1. 核心原理
instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链上的任何位置。
object instanceof Constructor
// 返回:`true` 如果 `object` 的原型链上存在 `Constructor.prototype`,否则 `false`。
2. 经典面试题:手写instanceof
/**
* 模拟 instanceof
* @param {Object} L 左侧对象 (实例)
* @param {Function} R 右侧构造函数
*/
function myInstanceof(L, R) {
// 1. 如果左侧不是对象,直接返回 false (基本类型排除)
if (L === null || typeof L !== 'object' && typeof L !== 'function') {
return false;
}
// 2. 获取右侧构造函数的原型
const prototype = R.prototype;
// 3. 获取左侧对象的原型 (Object.getPrototypeOf(L) 更好)
let proto = Object.getPrototypeOf(L); // 或者 L.__proto__
// 4. 循环向上查找原型链
while (true) {
if (proto === null) {
return false; // 到达链顶端 (Object.prototype.__proto__ === null)
}
if (proto === prototype) {
return true; // 找到了
}
proto = Object.getPrototypeOf(proto);
}
}
3. 面试考点
(1) 基础类型误区
instanceof 只能正确判断引用类型 (对象),对于基本类型字面量会失效。
'hello' instanceof String // false
new String('hello') instanceof String // true
(2) 原型链查找
Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
Object instanceof Function // true (最容易搞混)
解析:
Function 是所有函数的构造函数 (包括它自己)。
Function.__proto__ === Function.prototype -> true
Object 本身也是一个函数。
Object.__proto__ === Function.prototype -> true
(3) iframe 跨环境问题
如果你的页面主要包含一个 iframe,iframe 中的数组和主窗口的数组是不同的构造函数。
iframe.contentWindow.Array === Array // false
const arr = new iframe.contentWindow.Array();
arr instanceof Array // false
解决方案:使用 Array.isArray() 或 Object.prototype.toString.call(arr) === '[object Array]'。
(4) Symbol.hasInstance
ES6 允许通过 static 方法自定义 instanceof 行为。
class MyArray {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}
console.log([] instanceof MyArray); // true