xha*_*lix 86 javascript inheritance class ecmascript-6
是否可以在ES6中扩展一个类而不调用该super方法来调用父类?
编辑:这个问题可能会产生误导.它是我们必须打电话的标准super()还是我错过了什么?
例如:
class Character {
constructor(){
console.log('invoke character');
}
}
class Hero extends Character{
constructor(){
super(); // exception thrown here when not called
console.log('invoke hero');
}
}
var hero = new Hero();
Run Code Online (Sandbox Code Playgroud)
当我没有调用super()派生类时,我遇到了范围问题 - >this is not defined
我用iojs运行这个 - 在v2.3.0中的和声
log*_*yth 137
ES2015(ES6)课程的规则基本上归结为:
this直到super被调用才能使用.super如果它们是子类,或者它们必须显式返回一些对象来取代未初始化的对象.这归结为ES2015规范的两个重要部分.
第8.1.1.3.4节定义了决定this函数内容的逻辑.类的重要部分是它可能this处于一种"uninitialized"状态,并且当处于这种状态时,尝试使用this将抛出一个异常.
第9.2.2节,[[Construct]]定义了通过new或调用的函数的行为super.调用基类构造函数时,this在步骤#8初始化[[Construct]],但对于所有其他情况,this未初始化.在构造结束时,GetThisBinding调用,因此如果super尚未调用(因此初始化this),或者未返回显式替换对象,则构造函数调用的最后一行将引发异常.
Ami*_*mit 10
有多个答案和评论说明super 必须是内线的第一行constructor.这完全是错的.@loganfsmyth答案有必要的参考要求,但归结为:
Inheriting(extends)构造函数必须super在使用this之前和返回之前调用,即使this未使用它也是如此
请参阅下面的片段(适用于Chrome ...),了解为什么this在调用之前使用语句(不使用)可能有意义super.
'use strict';
var id = 1;
function idgen() {
return 'ID:' + id++;
}
class Base {
constructor(id) {
this.id = id;
}
toString() { return JSON.stringify(this); }
}
class Derived1 extends Base {
constructor() {
var anID = idgen() + ':Derived1';
super(anID);
this.derivedProp = this.baseProp * 2;
}
}
alert(new Derived1());Run Code Online (Sandbox Code Playgroud)
新的es6类语法只是带有原型的"旧"es5"类"的另一种表示法.因此,如果不设置其原型(基类),则无法实例化特定类.
这就像把奶酪放在你的三明治上而没有制作它.在制作三明治之前你也不能放奶酪,所以......
... this在调用超类之前使用关键字super()也是不允许的.
// valid: Add cheese after making the sandwich
class CheeseSandwich extend Sandwich {
constructor() {
super();
this.supplement = "Cheese";
}
}
// invalid: Add cheese before making sandwich
class CheeseSandwich extend Sandwich {
constructor() {
this.supplement = "Cheese";
super();
}
}
// invalid: Add cheese without making sandwich
class CheeseSandwich extend Sandwich {
constructor() {
this.supplement = "Cheese";
}
}
Run Code Online (Sandbox Code Playgroud)
如果未指定基类的构造函数,则使用以下定义:
constructor() {}
Run Code Online (Sandbox Code Playgroud)
对于派生类,使用以下默认构造函数:
constructor(...args) {
super(...args);
}
Run Code Online (Sandbox Code Playgroud)
编辑:发现这个developer.mozilla.org:
When used in a constructor, the super keyword appears alone and must be used before the this keyword can be used.
Run Code Online (Sandbox Code Playgroud)
如果在子类中完全省略构造函数,则可以在子类中省略 super()。“隐藏”的默认构造函数将自动包含在您的子类中。但是,如果您确实在子类中包含构造函数,则必须在该构造函数中调用 super()。
class A{
constructor(){
this.name = 'hello';
}
}
class B extends A{
constructor(){
// console.log(this.name); // ReferenceError
super();
console.log(this.name);
}
}
class C extends B{} // see? no super(). no constructor()
var x = new B; // hello
var y = new C; // hello
Run Code Online (Sandbox Code Playgroud)
阅读本文了解更多信息。
justyourimage 的答案是最简单的方法,但他的例子有点臃肿。这是通用版本:
class Base {
constructor(){
return this._constructor(...arguments);
}
_constructor(){
// just use this as the constructor, no super() restrictions
}
}
class Ext extends Base {
_constructor(){ // _constructor is automatically called, like the real constructor
this.is = "easy"; // no need to call super();
}
}
Run Code Online (Sandbox Code Playgroud)
不要扩展 real constructor(),只需使用 fake_constructor()进行实例化逻辑。
请注意,此解决方案使调试变得烦人,因为您必须为每个实例化进入一个额外的方法。