instanceof(原型链判断)
instanceof 用来判断:某个对象的原型链上,是否能找到某个构造函数的 prototype。
obj instanceof Ctor结论先说
instanceof判断的是 原型链关系,不是“类型”本身。- 左侧必须是对象(或函数),原始类型(
1/'a'/true/null/undefined)一般都是false。 - 右侧必须是“可作为构造器/有
prototype的对象”(通常是函数),否则会抛TypeError。
运行机制(核心原理)
在不考虑 Symbol.hasInstance 的情况下,x instanceof F 大致等价于:
1) 取到 F.prototype
2) 从 x 开始沿着 [[Prototype]](也就是 Object.getPrototypeOf(x))一直向上找
3) 如果某一层原型 === F.prototype,返回 true
4) 找到 null 还没找到,则返回 false
手写实现(推荐:循环版,避免递归栈)
/**
* 模拟默认语义:判断 ctor.prototype 是否在 obj 的原型链上
* 不包含 Symbol.hasInstance 的自定义逻辑
*/
export function myInstanceof(obj: unknown, ctor: any): boolean {
// 1) 原始值一定不是实例
if (obj === null || obj === undefined) return false;
const t = typeof obj;
if (t !== 'object' && t !== 'function') return false;
// 2) 右侧必须是对象/函数,并且要有可用的 prototype
// 原生 instanceof 在不合法时会抛 TypeError
if (ctor === null || (typeof ctor !== 'function' && typeof ctor !== 'object')) {
throw new TypeError('Right-hand side of instanceof is not an object');
}
const proto = (ctor as any).prototype;
if (proto === null || (typeof proto !== 'object' && typeof proto !== 'function')) {
throw new TypeError('Function has non-object prototype in instanceof check');
}
// 3) 沿原型链向上查找
let cur = Object.getPrototypeOf(obj as object);
while (cur !== null) {
if (cur === proto) return true;
cur = Object.getPrototypeOf(cur);
}
return false;
}示例
function Person() {}
const p = new (Person as any)();
myInstanceof(p, Person); // true
myInstanceof(p, Object); // true
myInstanceof({}, Person); // false
myInstanceof(1 as any, Number); // false(原始值)常见坑点
1) 跨 iframe / 跨 realm
不同 realm(例如 iframe)里有不同的全局构造函数:
- 另一个 iframe 创建的数组,
arr instanceof Array(当前窗口的 Array)可能是false
这种场景更推荐用:
Array.isArray(x)Object.prototype.toString.call(x)
2) prototype 可被篡改
Ctor.prototype 或对象的原型链都能被改,instanceof 结果也会变。
3) Object.create(null) 没有原型
const x = Object.create(null);
x instanceof Object; // false与 typeof / toString 的对比
typeof:适合区分原始类型与函数(例如typeof fn === 'function'),但对对象细分能力弱(数组/日期/正则都返回'object')instanceof:适合判断“是否由某构造函数的原型链派生”,但跨 realm 容易踩坑Object.prototype.toString.call(x):更稳定地识别内置类型([object Array]/[object Date]等)