在 JavaScript 中,检查对象是否继承自某个原型,主要使用 instanceof 操作符 和 Object.prototype.isPrototypeOf() 方法,两者各有适用场景,需根据需求选择。
1. 使用 instanceof 操作符- 作用:检测构造函数的 prototype 属性是否出现在对象的原型链中。
- 适用场景:基于构造函数或 class 的继承体系(如判断对象是否为某个类的实例)。
- 示例:class Animal {}class Dog extends Animal {}const dog = new Dog();console.log(dog instanceof Animal); // true
- 局限性:
跨 realm 问题:在 iframe 或不同全局环境中,内置构造函数(如 Array)的原型可能不同,导致 instanceof 失效。// 假设从 iframe 获取的数组const iframeArray = iframe.contentWindow.Array;const arr = new iframeArray();console.log(arr instanceof Array); // 可能为 false
Object.create(null) 对象:此类对象不继承 Object.prototype,instanceof Object 会返回 false。const obj = Object.create(null);console.log(obj instanceof Object); // false
2. 使用 Object.prototype.isPrototypeOf()3. 选择建议- 优先 instanceof:处理通过 new 或 class 创建的对象时,更直观且符合直觉。
- 优先 isPrototypeOf():需要健壮性检查、处理纯粹原型继承或跨环境时更可靠。
4. 注意事项(避坑指南)- 原始值无原型链:数字、字符串、布尔值等原始值不能使用 instanceof 或 isPrototypeOf()。const str = 'hello';console.log(str instanceof String); // false(原始值非对象)
- 避免 __proto__:非标准属性,直接操作可能影响性能,推荐使用 Object.getPrototypeOf() 和 Object.setPrototypeOf()。const obj = {};const proto = { type: 'custom' };Object.setPrototypeOf(obj, proto); // 正确设置原型
- 原型链终点为 null:所有对象的原型链最终指向 null,Object.create(null) 创建的对象无原型。const pureObj = Object.create(null);console.log(Object.prototype.isPrototypeOf(pureObj)); // false
5. 原型链的高级应用- 方法共享:原型对象上定义的方法可被所有实例共享,节省内存。function User(name) { this.name = name;}User.prototype.sayHello = function() { console.log(`Hello, ${this.name}`);};const user = new User('Alice');user.sayHello(); // "Hello, Alice"
- 实现 Polyfill:在 Array.prototype 或 String.prototype 上添加方法,兼容旧环境。if (!Array.prototype.flatMap) { Array.prototype.flatMap = function(callback) { // 实现 flatMap 逻辑 };}
- 理解内置方法:如 hasOwnProperty() 继承自 Object.prototype,调用时沿原型链查找。const obj = { prop: 'value' };console.log(obj.hasOwnProperty('prop')); // true
- 委托模式:对象将行为委托给原型对象处理。const handler = { handleEvent(event) { console.log(`Event handled: ${event.type}`); }};document.addEventListener('click', handler); // 委托给 handler
总结- instanceof:适合类实例判断,但需注意跨 realm 和 Object.create(null) 问题。
- isPrototypeOf():适合纯粹原型继承或跨环境检查,更底层可靠。
- 避坑:避免原始值、__proto__,理解原型链终点。
- 高级应用:利用原型链实现方法共享、Polyfill、委托模式等。