JavaScript ES6类扩展没有超级

是否有可能在ES6中扩展一个类而不调用super方法来调用父类?

编辑:这个问题可能是误导。 是我们必须调用super()还是缺less一些东西?

例如:

 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(); 

当我没有调用派生类super()我得到一个范围问题 – > this is not defined

我用v2.3.0中的iojs –harmony来运行这个

ES2015(ES6)类的规则基本上归结为:

  1. 在一个子类的构造函数中,只有在调用super才能使用它。
  2. 如果ES6类构造函数是子类,则必须调用super ,否则必须显式返回一些对象来代替未初始化的对象。

这归结于ES2015规范的两个重要部分。

第8.1.1.3.4节定义了决定thisfunction的逻辑。 类的重要组成部分是,它有可能处于"uninitialized"状态,并且在这种状态下,试图使用this将会抛出exception。

第9.2.2节, [[Construct]] ,它定义了通过newsuper调用的函数的行为。 当调用一个基类的构造函数时, this[[Construct]]第8步被初始化,但是对于所有其他的情况, this是未初始化的。 在构造结束时, GetThisBinding ,所以如果super还没有被调用(因此初始化),或者没有返回一个显式的replace对象,构造函数调用的最后一行会抛出一个exception。

有多个答案和评论指出, super 必须constructor内的第一行。 这是完全错误的。 @loganfsmyth答案有要求的必要参考,但归结为:

inheritance( extends )的构造函数必须在使用之前和返回之前调用super ,即使this不使用

看到下面的片段(在Chrome中工作…),看看为什么在调用super之前有声明(不使用this )是有意义的。

 '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()); 

只是注册发布这个解决scheme,因为这里的答案不满足我至less,因为实际上有一个简单的方法来解决这个问题。 调整你的类创build模式来覆盖子方法中的逻辑,同时只使用超级构造函数并将构造函数的参数转发给它。

正如你不要在你的子类本身中创build一个构造函数,而只是引用在相应的子类中覆盖的方法。

这意味着你可以从你自己的构造函数中解脱出来,并且避免使用常规的方法 – 当你让自己select你想要调用的超级(完全)的时候,可以重写并且不强制执行super可选)例如:

 super.ObjectConstructor(...) 
 class Observable { constructor() { return this.ObjectConstructor(arguments); } ObjectConstructor(defaultValue, options) { this.obj = { type: "Observable" }; console.log("Observable ObjectConstructor called with arguments: ", arguments); console.log("obj is:", this.obj); return this.obj; } } class ArrayObservable extends Observable { ObjectConstructor(defaultValue, options, someMoreOptions) { this.obj = { type: "ArrayObservable" }; console.log("ArrayObservable ObjectConstructor called with arguments: ", arguments); console.log("obj is:", this.obj); return this.obj; } } class DomainObservable extends ArrayObservable { ObjectConstructor(defaultValue, domainName, options, dependent1, dependent2) { this.obj = super.ObjectConstructor(defaultValue, options); console.log("DomainObservable ObjectConstructor called with arguments: ", arguments); console.log("obj is:", this.obj); return this.obj; } } var myBasicObservable = new Observable("Basic Value", "Basic Options"); var myArrayObservable = new ArrayObservable("Array Value", "Array Options", "Some More Array Options"); var myDomainObservable = new DomainObservable("Domain Value", "Domain Name", "Domain Options", "Dependency A", "Depenency B"); 

新的es6类语法只是原型的“旧”es5“类”的其他符号。 因此,如果不设置原型(基类),就不能实例化特定的类。

这就像把奶酪放在你的三明治上而没有做到。 制作三明治之前 ,你也不能放奶酪,所以…

…在super()调用super类之前使用this关键字也是不允许的。

 // 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"; } } 

如果您不指定基类的构造函数,则使用以下定义:

 constructor() {} 

对于派生类,使用以下默认构造函数:

 constructor(...args) { super(...args); } 

编辑:find这个在developer.mozilla.org

 When used in a constructor, the super keyword appears alone and must be used before the this keyword can be used. 

资源

尝试:

 class Character { constructor(){ if(Object.getPrototypeOf(this) === Character.prototype){ console.log('invoke character'); } } } class Hero extends Character{ constructor(){ super(); // throws exception when not called console.log('invoke hero'); } } var hero = new Hero(); console.log('now let\'s invoke Character'); var char = new Character(); 

演示

如果你打算开发下面的OOP概念,我会推荐使用OODK-JS 。

 OODK(function($, _){ var Character = $.class(function ($, µ, _){ $.public(function __initialize(){ $.log('invoke character'); }); }); var Hero = $.extends(Character).class(function ($, µ, _){ $.public(function __initialize(){ $.super.__initialize(); $.log('invoke hero'); }); }); var hero = $.new(Hero); }); 

简单的解决scheme:我认为它明显不需要解释。

 class ParentClass() { constructor(skipConstructor = false) { // default value is false if(skipConstructor) return; // code here only gets executed when 'super()' is called with false } } class SubClass extends ParentClass { constructor() { super(true) // true for skipping ParentClass's constructor. // code } } 

如果您在子类中完全省略构造函数,则可以省略子类中的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 

阅读此以获取更多信息。