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");
};
}
}
_
this
は、親B
での構築中に、まだ子A
を指しているようです。そのため、親A
のfoo
に到達できません。
コンストラクタチェーン中に子によってオーバーライドされている親バージョン関数を呼び出すthis
を作成するにはどうすればよいですか?
または、このようなシナリオになると、より良い解決策はありますか?
編集
したがって、答えを読んだ後、主な質問は次のようになります-
子供がオーバーライドする可能性があるため、JavaScriptのコンストラクタに_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
になります。
子供は関数をオーバーライドできるので、これは悪い考えですか?
_class A{
constructor(name){
this.setName(name); // Is it bad?
}
...
}
_
だから、Java、C++などのコンストラクタで_initialize helpers
_または_setter functions
_を使用しないでください...?
new A().init()
のようなものを手動で呼び出して、初期化を支援する必要がありますか?
派生クラスA
のコンストラクターにいるとき、2つのオブジェクトB
とB
があると誤解して操作しているようです。これはまったく当てはまりません。オブジェクトは1つだけです。 A
とB
は両方とも、その1つのオブジェクトにプロパティとメソッドを提供します。 this
の値は、クラスBのオブジェクトの作成中のB
のコンストラクターと同じように、A
のコンストラクターと同じになります。
ES6クラスの構文は、オブジェクトタイプのプロトタイプを使用するES5メソッドの単なるシュガーであり、実際、プロトタイプはまだ裏で使用されています。したがって、クラスBで行うように、派生クラスでメソッドfoo
を定義する場合、それはまだプロトタイプに割り当てられており、その割り当ては、プロトタイプに既に存在する可能性がある同じ名前のメソッドをオーバーライドします親定義から来ました。これが、this.foo()
がfoo
のクラスBバージョンを参照する理由です。 foo
のクラスAバージョンに到達したい場合は、すでに知っているように見えるように、super
を使用して手動で指定する必要があります。
特定の質問に関して:
これは、親Aでの構築中にまだ子Bを指しているようです。そのため、親Aのfooに到達できません。
子Bと親Aは別個のオブジェクトではありません。親Aと子Bの両方が参照するオブジェクトが1つあります。親Aおよび子Bのメソッドまたはコンストラクターは、this
とまったく同じ値を参照します。
コンストラクタチェーン中に子によってオーバーライドされている親バージョン関数を呼び出すようにするにはどうすればよいですか?
super
を使用して、既にわかっているように親メソッドを直接参照します。
または、このようなシナリオになると、より良い解決策はありますか?
super
はソリューションです。
参考までに、これはsuper
の仕組みを含むES6クラスに関する非常に良い議論です。 ECMAScript 6のクラス(最終セマンティクス) 。セクション4.4はあなたの質問/理解に特に関係があるようです。