js怎么检查对象是否继承自某个原型

js怎么检查对象是否继承自某个原型
最新回答
風的廻喑

2021-07-30 11:36:53

在 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()
  • 作用:检查一个对象是否存在于另一个对象的原型链上,不依赖构造函数。
  • 适用场景:纯粹原型继承、跨环境判断或不确定对象来源时。
  • 示例:const myProto = { type: 'animal' };const someObject = Object.create(myProto);console.log(myProto.isPrototypeOf(someObject)); // true
  • 优势

    更底层:直接检查原型链,不受构造函数或 prototype 修改的影响。

    跨环境可靠:即使对象通过 Object.create() 创建,也能正确判断。

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、委托模式等。