ES 6 Classのsuperキーワード
以下は個人の学習ノートです.
superというキーワードは、関数としてもオブジェクトとしても使用できます.この2つの場合、その使い方は全く違います.
なお、superは親クラスAのコンストラクション関数を表すが、サブクラスBの例、すなわちsuper内部のthisはBを指すため、super()はここではA.prototypeに相当する.constructor.call(this).
super()が実行されると、親Aのコンストラクタではなく、サブクラスBのコンストラクタを指すことがわかります.すなわち,super()内部のthisはBを指す.
一般的な方法では、親のプロトタイプオブジェクトを指します.静的メソッドでは、親を指します.
上のコードでは、サブクラスBのsuper.c()は,superを1つのオブジェクトとして使用する.このとき、superは一般的な方法の中で、A.prototypeを指すので、super.c()はA.prototypeに相当する.c().
親クラスのメソッドをsuperで呼び出すと、superは子クラスのthisをバインドします.
上のコードではsuper.s()はA.prototypeを呼び出したが.でもA.prototype.s()はサブクラスBのthisをバインドし、1ではなく2を出力します.つまり、実際に実行するのはsuperである.s.call(this).
サブクラスのthisをバインドするため、superによって属性に値を割り当てると、superがthisとなり、値を割り当てる属性がサブクラスインスタンスの属性になります.
上のコードではsuper.xは3に割り当てられ、この場合はthisに等しい.xは3に割り当てられます.superを読み出すとxの時、A.prototypeと読みました.xなのでundefinedを返します.
superを使用する場合は、関数として使用するか、オブジェクトとして使用するかを明示的に指定する必要があります.そうしないと、エラーが発生します.
上のコードではconsole.log(super)の中のsuperは、関数として使うのか、オブジェクトとして使うのかわからないので、JavaScriptエンジンがコードを解析するときにエラーを報告します.この場合,superのデータ型を明確に示すことができれば,エラーは報告されない.
最後に、オブジェクトは常に他のオブジェクトを継承するため、superキーワードは任意のオブジェクトで使用できます.
superというキーワードは、関数としてもオブジェクトとしても使用できます.この2つの場合、その使い方は全く違います.
1、関数として使う
class A {}
class B extends A {
constructor() {
super(); //ES6 , super 。
}
}
なお、superは親クラスAのコンストラクション関数を表すが、サブクラスBの例、すなわちsuper内部のthisはBを指すため、super()はここではA.prototypeに相当する.constructor.call(this).
class A {
constructor() {
console.log(new.target.name); //new.target
}
}
class B extends A {
constructor() {
super();
}
}
new A() // A
new B() // B
super()が実行されると、親Aのコンストラクタではなく、サブクラスBのコンストラクタを指すことがわかります.すなわち,super()内部のthisはBを指す.
2、対象として使う
一般的な方法では、親のプロトタイプオブジェクトを指します.静的メソッドでは、親を指します.
class A {
c() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.c()); // 2
}
}
let b = new B();
上のコードでは、サブクラスBのsuper.c()は,superを1つのオブジェクトとして使用する.このとき、superは一般的な方法の中で、A.prototypeを指すので、super.c()はA.prototypeに相当する.c().
親クラスのメソッドをsuperで呼び出すと、superは子クラスのthisをバインドします.
class A {
constructor() {
this.x = 1;
}
s() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
m() {
super.s();
}
}
let b = new B();
b.m() // 2
上のコードではsuper.s()はA.prototypeを呼び出したが.でもA.prototype.s()はサブクラスBのthisをバインドし、1ではなく2を出力します.つまり、実際に実行するのはsuperである.s.call(this).
サブクラスのthisをバインドするため、superによって属性に値を割り当てると、superがthisとなり、値を割り当てる属性がサブクラスインスタンスの属性になります.
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
上のコードではsuper.xは3に割り当てられ、この場合はthisに等しい.xは3に割り当てられます.superを読み出すとxの時、A.prototypeと読みました.xなのでundefinedを返します.
superを使用する場合は、関数として使用するか、オブジェクトとして使用するかを明示的に指定する必要があります.そうしないと、エラーが発生します.
class A {}
class B extends A {
constructor() {
super();
console.log(super); //
}
}
上のコードではconsole.log(super)の中のsuperは、関数として使うのか、オブジェクトとして使うのかわからないので、JavaScriptエンジンがコードを解析するときにエラーを報告します.この場合,superのデータ型を明確に示すことができれば,エラーは報告されない.
最後に、オブジェクトは常に他のオブジェクトを継承するため、superキーワードは任意のオブジェクトで使用できます.