You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Object.setPrototypeOf时super()为何调用错误构造函数?

关于ES6类中super()调用与Object.setPrototypeOf的疑问

代码示例

class Polygon {
  constructor() {
    this.name = "Polygon";
  }
}

class Rectangle {
  constructor() {
    this.name = "Rectangle";
  }
}

class Square extends Polygon {
  constructor() {
    super(); 
  }
}

Object.setPrototypeOf(Square, Rectangle);

const instance = new Square();

console.log(instance.name); // Rectangle

我的理解

  • instance.__proto__:指向Square.prototype,用于继承实例方法。
  • Square.__proto__:指向Rectangle,用于继承静态方法和属性。
  • Square.prototype.__proto__:指向Polygon.prototype,用于继承父类的实例方法。

疑问

调用Object.setPrototypeOf(Square, Rectangle)后,Square.__proto__指向Rectangle以继承静态属性,而Square.prototype.__proto__仍指向Polygon.prototype。我认为Square继承自Polygon,super()应调用Polygon的构造函数,但实际却调用了Rectangle的构造函数,想了解调用该方法后具体改变了什么,填补认知空缺。


解答

你这里的核心误解在于**super()在子类构造函数中的调用逻辑**:它并不是根据实例的原型链(Square.prototype.__proto__)来查找父类构造函数,而是根据子类自身的原型链(也就是Square.__proto__)来确定要调用的构造函数。

具体来说:

  1. 当你用class Square extends Polygon定义类时,JS引擎会自动把Square的原型(Square.__proto__)设置为Polygon,同时把Square.prototype.__proto__设置为Polygon.prototype,这就建立了两条独立的继承链:
    • 类继承链:Square → Polygon → Function.prototype(负责静态成员的继承)
    • 实例继承链:instance → Square.prototype → Polygon.prototype(负责实例成员的继承)
  2. 此时Square构造函数里的super(),会沿着类继承链找到Polygon的构造函数并调用,给this.name赋值为"Polygon"。
  3. 但当你执行Object.setPrototypeOf(Square, Rectangle)后,类继承链被修改了:Square.__proto__从Polygon变成了Rectangle,现在类继承链变成Square → Rectangle → Function.prototype。
  4. 这时候super()的调用逻辑就会沿着修改后的类继承链,找到Rectangle的构造函数并执行,于是this.name被赋值为"Rectangle",最终输出结果就是这个值。

简单来说,super()在构造函数中的行为只关心子类本身的原型指向哪个类,和实例原型链的父类没有直接关系。你修改了子类的原型指向,就等于改变了super()要调用的父类构造函数。

内容的提问来源于stack exchange,提问作者jimo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 02:22:13