This question already has an answer here:
Parent constructor call overridden functions before all child constructors are finished

(1个答案)


5年前关闭。




我在下面遇到了JavaScript(ES6)问题
class A{
  constructor(){
    this.foo();
  }
  foo(){
    console.log("foo in A is called");
  }
}

class B extends A{
  constructor(){
    super();
    this.foo();
  }
  foo(){
    console.log("foo in B is called");
  }
}

我期望的是
foo in A is called
foo in B is called

但实际上是
foo in B is called
foo in B is called

我知道我可以通过在B类的foo函数中添加super.foo()来解决此问题
class B extends A{
  constructor(){
    super();
    this.foo();
  }
  foo(){
    super.foo() // add this line
    console.log("foo in B is called");
  }
}

但是,想象一下类似的情况:

子级必须重写父级的功能,以完成一些额外的工作,并防止外部访问能够访问原始项。
class B extends A{
  constructor(){
    super();
    this.initBar();
  }
  foo(){
    super.foo();
    this.bar.run(); //undefined
    console.log("foo in B is called");
  }
  initBar(){
    this.bar.run = function(){
      console.log("bar is running");
    };
  }
}

似乎在构建父thisB仍指向子A。这就是为什么我无法到达父Afoo的原因。

如何使this调用构造函数链中被子项覆盖的父版本函数?

还是在这种情况下有更好的解决方案?

编辑

因此,在阅读答案后,主要问题变为-

不鼓励在 child 的JavaScript中将initialize helperssetter functions放在JavaScript的构造函数中吗?

为了更清楚地说明情况:(很抱歉,我之前的错误示例:()
class A{
  constructor(name){
    this.setName(name);
  }
  setName(name){
    this._name = name;
  }
}

class B extends A{
  constructor(name){
    super(name);
    this._div = document.createElementById("div");
  }
  setName(name){
    super.setName(name);
    this._div.appendChild(document.createTextNode(name));
  }
}

new B("foo")
this._div将是undefined

这是个坏主意,因为 child 可以覆盖该功能吗?
class A{
  constructor(name){
    this.setName(name); // Is it bad?
  }
  ...
}

所以我不应该像Java,C++那样在构造函数中使用initialize helperssetter functions ...?

我必须手动调用类似new A().init()的东西来帮助我初始化吗?

最佳答案

您似乎误以为在派生类A的构造函数中有两个对象BB。根本不是这种情况。只有一个对象。 AB都为该对象提供属性和方法。在创建B类对象的过程中,this的值在B的构造函数中与在A的构造器中相同。

ES6类语法仅是将ES5方法用于对象类型的原型(prototype),而实际上,原型(prototype)仍在幕后使用。这样,当您像在类B中一样在派生类中定义方法foo时,它仍在分配给原型(prototype),并且该分配会覆盖来自父定义的原型(prototype)上可能已经存在的任何同名方法。这就是this.foo()引用foo的B类版本的原因。如果您想达到A类版本的foo,那么您将已经手动使用super进行指定,就像您已经知道的那样。

至于您的具体问题:



子B和父A不是独立的对象。父级A和子级B都引用一个对象。父A和子B的方法或构造函数将看到this的值完全相同。



您似乎已经知道,可以使用super直接引用父方法。


super是解决方案。

仅供引用,这是关于ES6类的很好的讨论,包括super的工作方式:Classes in ECMAScript 6 (final semantics)。第4.4节似乎与您的问题/理解特别相关。

10-05 20:57
查看更多