我在下面遇到了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");
}
}
但想象一下类似的情况:
Child必须覆盖父级的功能才能执行一些额外的工作,并阻止外部访问能够访问原始功能。
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");
};
}
}
在父this
中构建时,B
似乎仍指向子A
。这就是为什么我无法联系到父A
的{{1}}。
如何让foo
调用构造函数链中被子进程覆盖的父版本函数?
或者在这样的场景中有没有更好的解决方案?
修改
因此,在阅读答案后,主要问题变为 -
是否不建议在JavaScript中将this
或initialize helpers
置于构造函数中,因为孩子有机会覆盖它们?
更清楚地澄清情况:(对不起我之前的坏例子:()
setter functions
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
所以我不应该像Java,C ++那样在构造函数中使用class A{
constructor(name){
this.setName(name); // Is it bad?
}
...
}
或initialize helpers
?
我是否必须手动调用此setter functions
之类的内容来帮助我初始化内容?
答案 0 :(得分:18)
当您处于派生类A
的构造函数中时,您似乎在误解下有两个对象B
和B
。事实并非如此。只有一个对象。 A
和B
都为这一个对象提供了属性和方法。 this
的构造函数中的B
的值与在创建B类对象期间A
的构造函数中的值相同。
ES6类语法只是使用原型用于对象类型的ES5方法的糖,事实上,原型仍然在封面下使用。因此,当您在类B中定义派生类中的方法foo
时,它仍然会分配给原型,并且该赋值将覆盖原型上可能已存在的任何同名方法。来自父定义。这就是this.foo()
引用foo
的B类版本的原因。如果您想要达到foo
的A级版本,那么您将使用super
手动指定该版本,因为您似乎已经知道了。
至于你的具体问题:
似乎这仍然指向孩子B在建造时 父母A.这就是为什么我无法联系父母A的原因。
子B和父A不是单独的对象。父A和子B都有一个对象引用。父A和子B方法或构造函数将看到完全相同的this
值。
如何使其调用正在进行的父版本功能 在构造函数链中由子进行覆盖?
您可以使用super
直接引用父方法,因为您似乎已经知道了。
或者在这样的场景中有没有更好的解决方案?
super
是解决方案。
仅供参考,这是关于ES6课程的一个非常好的讨论,包括super
的工作原理:Classes in ECMAScript 6 (final semantics)。第4.4节似乎与您的问题/理解特别相关。