ES6 类继承中 super 关键字的作用是什么?
super 在 ES6 类继承中有两种用法:作为函数调用和作为对象引用。核心要点是——super() 调用父类构造函数,super.method() 调用父类原型方法,super.staticMethod() 在静态方法中调用父类静态方法。
super() 作为函数调用
在子类 constructor 中,super() 调用父类构造函数。ES6 的继承机制规定:父类负责创建 this 对象,子类负责在此基础上添加属性。因此 super() 必须在 this 之前调用,否则会抛出 ReferenceError。
javascriptclass Parent { constructor(name) { this.name = name; } } class Child extends Parent { constructor(name, age) { super(name); // 必须先调 super,否则下面用 this 会报错 this.age = age; } }
如果子类没有显式定义 constructor,引擎会自动插入一个默认的 constructor(...args) { super(...args); }。
super.method() 作为对象引用
在子类普通方法中,super 指向父类的 prototype,可以调用父类原型上的方法:
javascriptclass Parent { greet() { return 'hello from Parent'; } } class Child extends Parent { greet() { return super.greet() + ' and Child'; } } new Child().greet(); // "hello from Parent and Child"
静态方法中的 super
在子类静态方法中,super 指向父类本身(而非 prototype),因此可以调用父类的静态方法:
javascriptclass Parent { static create() { return new this(); } } class Child extends Parent { static create() { return super.create(); // 调用 Parent.create() } }
super 的内部指向总结
| 使用场景 | super 指向 |
|---|---|
super() 在 constructor 中 | 父类构造函数 |
super.method() 在普通方法中 | Parent.prototype |
super.method() 在静态方法中 | 父类本身(Parent) |
super.x = value | 触发父类原型上的 setter(如果有) |
追问:子类 constructor 为什么必须先调 super?
ES6 类的继承与 ES5 的寄生组合继承有本质区别。ES5 中是先创建 this(子类自己的对象),再用 Parent.apply(this) 借用父类构造函数挂属性。ES6 反过来了——由父类构造函数先创建并初始化 this,子类再修改。这个顺序由 new.target 控制:当 new Child() 执行时,new.target 是 Child,但 this 的创建权在 Parent 那里。super() 执行后 this 才可用。
追问:super.x = value 有什么陷阱?
给 super 的属性赋值时,并不会像直觉那样去修改父类原型上的属性。实际行为是:如果父类原型上定义了该属性的 setter,赋值操作会触发那个 setter,this 指向当前子类实例;如果没有 setter,则相当于直接在 this 上创建属性:
javascriptclass Parent { set x(val) { console.log('setter called with', val); } } class Child extends Parent { setX() { super.x = 42; // 触发 Parent.prototype 的 setter } } new Child().setX(); // "setter called with 42"
追问:ES6 继承与 ES5 原型继承的区别
| ES5 寄生组合继承 | ES6 class 继承 | |
|---|---|---|
| this 创建 | 子类先创建 this,再借用父类 | 父类构造函数创建 this |
| super | 无,用 Parent.call(this) | super() 必须 |
| 原型链 | 手动 Object.create(Parent.prototype) | extends 自动建立 |
| 静态方法 | 不会继承 | 自动继承 |
| new.target | 不存在 | 控制实例化行为 |