instanceof判断依赖原型链真实存在且未被切断;new调用确保实例__proto__指向构造函数prototype;重写prototype需保留constructor;子类继承须用object.setprototypeof或extends维持链路;避免__proto__篡改、跨iframe及错误赋值。

instanceof 判断自定义原型链,关键不是“写对代码”,而是确保原型链真实存在且未被意外切断或覆盖。
构造函数的 prototype 必须被实例正确继承
只要用 new 调用构造函数,实例的 __proto__ 就会自动指向该函数的 prototype。但若手动重写 prototype,必须同步修正 constructor,否则不影响 instanceof,但可能干扰调试和继承逻辑:
- 错误写法:
MyClass.prototype = { method() {} };→ 丢失constructor,虽不直接导致 instanceof 失效,但子类继承时容易出错 - 正确写法:
MyClass.prototype = { constructor: MyClass, method() {} };或更稳妥地用Object.defineProperty设置writable: false
继承链要靠 Object.setPrototypeOf 或 class extends 维护
子类要能被父类的 instanceof 识别,原型链必须连通:
- ES6 class 写法天然支持:
class Child extends Parent→Child.prototype.__proto__ === Parent.prototype - 函数式继承需显式设置:
Child.prototype = Object.create(Parent.prototype);,不能直接赋值空对象 - 避免用
Child.prototype = new Parent():会执行父类构造逻辑,可能产生副作用,且实例属性混入原型
警惕原型链被中途篡改
以下操作会破坏 instanceof 的预期行为:
- 直接修改实例的
__proto__(如obj.__proto__ = {})→ 原型链断裂,obj instanceof OriginalConstructor变为false - 用
Object.setPrototypeOf(obj, null)→ 链条提前终止,所有 instanceof 检查都返回false - 在 iframe 或不同上下文创建对象 → 构造函数不共享,
instanceof失效(此时应改用toString.call())
可选:自定义 Symbol.hasInstance 实现灵活判断
如果需要绕过默认原型链检查(比如模拟多继承、兼容旧数据结构),可在构造函数上定义:
MyType[Symbol.hasInstance] = function (obj) {
return obj && typeof obj === 'object' && 'customFlag' in obj;
};
这样 obj instanceof MyType 就不再查原型链,而是执行你写的逻辑。注意仅限构造函数自身使用,不影响其子类(除非子类也重写了该 symbol)。











