instanceof 的行为可通过重写构造函数的 symbol.hasinstance 静态方法自定义,该方法接收左侧操作数并返回布尔值,优先级高于原型链检查,支持脱离原型系统判定任意值是否为某类型的实例。

instanceof 的行为可以被自定义,核心在于重写构造函数的 Symbol.hasInstance 静态方法。它不依赖原型链硬编码逻辑,而是交由开发者控制“某值是否被视为该类型的实例”这一判断。
Symbol.hasInstance 是什么
它是 ES6 引入的一个内置 symbol,用于定义对象在使用 obj instanceof Constructor 时的判定逻辑。当 JS 引擎执行 instanceof 检查时,会优先查找右侧构造函数(Constructor)上是否存在 [Symbol.hasInstance] 方法;如果存在,就直接调用它,并把左侧操作数(obj)作为唯一参数传入,返回布尔值决定结果。
如何劫持 instanceof 行为
只需在构造函数(或任意函数)上定义静态的 [Symbol.hasInstance] 方法:
- 该方法必须是静态的(定义在函数本身,而非 prototype 上)
- 签名固定为
(value) => boolean,value 是 instanceof 左侧的操作数 - 返回 true 表示“视为该类型实例”,false 则否
例如:
class MyType {}
MyType[Symbol.hasInstance] = function (target) {
return target != null && typeof target === 'object' && 'customFlag' in target;
};
console.log({ customFlag: true } instanceof MyType); // true
console.log({}) instanceof MyType; // false
常见用途与注意事项
- 可用来模拟接口/契约检查:比如判定一个对象是否满足某组方法签名,而非继承自某个类
- 可用于跨 Realm(如 iframe)场景,绕过原型链断裂问题——因为 Symbol.hasInstance 是函数调用,不依赖共享的 prototype
- 不能在箭头函数中定义,因为它需要绑定 this(即构造函数自身),而箭头函数没有 this 绑定
- 若同时存在
[Symbol.hasInstance]和传统原型链匹配,前者具有更高优先级,完全取代默认行为
与传统 instanceof 的差异
原生 instanceof 仅检查 value.__proto__ === Constructor.prototype 或沿原型链向上查找是否匹配。而 Symbol.hasInstance 允许你完全脱离原型系统——甚至可以让字符串、数字、null 等非对象值“成为”某个类型的实例(只要逻辑允许):
function AlwaysTrue() {}
AlwaysTrue[Symbol.hasInstance] = () => true;
console.log(42 instanceof AlwaysTrue); // true
console.log(null instanceof AlwaysTrue); // true
console.log("hello" instanceof AlwaysTrue); // true










