在JavaScript(ES6)中的构造函数链中调用父代函数被子代码覆盖 [英] Call parent function which is being overridden by child during constructor chain in JavaScript(ES6)

查看:170
本文介绍了在JavaScript(ES6)中的构造函数链中调用父代函数被子代码覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面遇到一个问题(ES6)

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

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

我期待的是

  foo在A中称为
foo在B中称为

但实际上它是B中的
foo在B中被称为
foo

 被称为

我知道我可以通过添加 super.foo )B类的foo函数

  class B extends A {
constructor(){
super();
this.foo();
}
foo(){
super.foo()//添加此行
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 running running);
};
}
}

似乎 / code>仍然指向孩子 B 而在父 A 中构建。这就是为什么我不能到达父母 A foo



如何使这个调用在构造函数链中被子代覆盖的父版本函数?



或者有什么更好的解决方案吗?



谢谢。



<强>编辑



谢谢你们回答。



所以,在阅读答案后,主要问题变成 -



是不鼓励放 c> c $ c>或 setter函数在JavaScript中的构造函数中,因为孩子有机会覆盖它们 p>

为了更清楚地说明情况:(对于我以前的错误示例:(对不起)

  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 未定义


$ b $这是一个坏主意,因为孩子将能够覆盖函数?

  class A {
constructor(name){
this.setName(name); //不好
}
...
}

所以我不应该'在Java,C ++ ...中使用 initialize helpers setter函数在构造函数中?



我必须手动调用这个新的A()。init()来帮助我初始化东西?



再次感谢您。

解决方案

您似乎在误解之下操作有两个对象当您在派生类的构造函数中时, A B B 。根本不是这样。只有一个对象。 A B 为该对象提供属性和方法。 这个的值在 B 的构造函数中是相同的,因为它在<$ c $在创建B类对象时,c> A



ES6类语法仅仅是使用原型的ES5方法对象类型,实际上原型仍然在封面下使用。因此,当您在派生类中定义一个方法 foo ,就像您在类B中一样,它仍然分配给原型,该赋值覆盖任何同名的方法这可能已经存在于来自父定义的原型上。这就是为什么 this.foo()指的是B类版本的 foo 。如果要达到A类版本的 foo ,那么您将手动指定使用 super 已经知道。



对于您的具体问题:


这仍然指向孩子B,而在
父母A中构建。这就是为什么我不能到达父母A的foo。


孩子B和父母A不是单独的对象。父对象A和子类B都有一个对象。父母A和子B的方法或构造函数将会看到与完全相同的值


如何让这个调用父版本的函数在构造函数链中被
覆盖?



或 c在这种情况下,有没有更好的解决方案?


super 是解决方案。






FYI,这是一个很好的讨论ES6类,包括如何 super 的作品: ECMAScript 6中的课程(最终语义)。第4.4节似乎与您的问题/理解特别相关。


I've encounter a problem below with 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");
  }
}

What I expect is

foo in A is called
foo in B is called

But actually it is

foo in B is called
foo in B is called

I know I can resolve this by simply adding super.foo() in class B's foo function

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

But imagine a scenario similar to this:

Child has to override parent's function in order to do some extra works and prevent access from outer being able to access to the original one.

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

It seems that this still points to child B while constructing in parent A. That's why I can't reach parent A's foo.

How do I make this to call parent version function which is being overridden by child during constructor chain?

Or is there any better solution when it comes to scenario like this?

Thank you.

Edit

Thank you guys for answering.

So, after reading answers, the main question becomes --

Is it discouraged to put initialize helpers or setter functions in constructor in JavaScript since children have a chance to override them?

To clarify the situation more clearly: (sorry for my previous bad example :( )

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 will be undefined.

Is this a bad idea since child will be able to override the function?

class A{
  constructor(name){
    this.setName(name); // Is it bad?
  }
  ...
}

So I shouldn't use initialize helpers or setter functions in constructor like in Java, C++...?

Must I manually call things like this new A().init() to help me initialize things?

Thank you again.

解决方案

You seem to be operating under a misconception that there are two objects A and B when you are in the constructor of the derived class B. This is not the case at all. There is one and only one object. Both A and B contribute properties and methods to that one object. The value of this will be the same in the constructor for B as it is in the constructor for A during the creation of an object of class B.

The ES6 class syntax is just sugar over the ES5 method of using prototypes for object types and, in fact, the prototype is still used under the covers. As such, when you define a method foo in a derived class like you do in class B, it is still assigning to the prototype and that assignment overrides any method of the same name that might already exist on the prototype that came from the parent definition. This is why this.foo() refers to the class B version of foo. If you want to reach the class A version of foo, then you will have manually specify that using super as you appear to already know.

As for your specific questions:

It seems that this still points to child B while constructing in parent A. That's why I can't reach parent A's foo.

child B and parent A are not separate objects. There is one object that both parent A and child B reference. parent A and child B methods or constructors will see the exact same value of this.

How do I make this to call parent version function which is being overridden by child during constructor chain?

You use super to reference parent methods directly as you appear to already know.

Or is there any better solution when it comes to scenario like this?

super is the solution.


FYI, this is a pretty good discussion on ES6 classes including how super works: Classes in ECMAScript 6 (final semantics). Section 4.4 seems particularly relevant to your question/understanding.

这篇关于在JavaScript(ES6)中的构造函数链中调用父代函数被子代码覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆