ECMAScript 6-Classの継承
5636 ワード
基本的な使い方
Class間では
extends
のキーワードで継承を実現できます.これはES 5のプロトタイプチェーンの修正による継承よりも、明確で便利です.class Test extends Component {}
上記のコードは、
Test
クラスを定義し、extends
キーワードを介してComponent
クラスのすべての属性と方法を継承します.しかし、コードが配置されていないため、この2つのクラスは完全に同じであり、Component
クラスがコピーされたことに等しい.次に、Test
の内部にコードを追加します.class Test extends Component {
constructor(props) {
super(props); // constructor(props)
}
toTest() {
super.toTest(); // toTest()
}
}
上記のコードでは、
constructor
メソッドとtoTest
メソッドの両方に、親の構造関数を表し、親のthisオブジェクトを新規作成するためのsuper
キーワードが表示されます.サブクラスは、
constructor
メソッドでsuper
メソッドを呼び出さなければなりません.そうしないと、インスタンスを新規作成するとエラーが発生します.これは、子が自分のthis
オブジェクトを持たず、親のthis
オブジェクトを継承して加工するためである.super
メソッドを呼び出さないと、サブクラスはthis
オブジェクトを取得できません.class Component {}
class Test extends Component {
cosntructor() {
}
}
let a = new Test();
上記のコードでは、
Test
は親Component
を継承していますが、そのコンストラクション関数はsuperメソッドを呼び出さず、新しいインスタンス・タイムズが間違っています.ES 5の継承は、本質的には、サブクラスのインスタンスオブジェクト
this
を作成した後、親のメソッドをthis
に追加する(Parent.apply(this)
).ES 6の継承メカニズムはまったく異なり、実質的には、親のインスタンスオブジェクトthis
を作成し(したがって、super
メソッドを呼び出す必要がある)、次いで、this
をサブクラスの構造関数で変更する.サブクラスが
constructor
メソッドを定義していない場合、このメソッドはデフォルトで追加されます.コードは次のとおりです.すなわち、明示的な定義があるかどうかにかかわらず、どのサブクラスにもconstructor
の方法がある.constructor(...args) {
super(...args);
}
もう1つ注意しなければならないのは、サブクラスのコンストラクション関数でsuperを呼び出した後にのみthisキーワードを使用できます.そうしないと、エラーが発生します.これは、サブクラスインスタンスの構築が、親インスタンスの加工に基づいており、superメソッドのみが親インスタンスを返すためです.
class Component {
constructor(props) {
this.props = props;
}
}
class Test extends Component {
cosntructor(props, a) {
this.a = a; // ReferenceError
super(props);
this.a = a; //
}
}
上記のコードでは、サブクラスの
constructor
メソッドがsuper
を呼び出さない前に、this
キーワードを使用し、結果をエラーとして報告し、super
メソッドの後に置くのが正しい.クラスのprototypeプロパティとprotoプロパティ
ほとんどのブラウザのES 5インプリメンテーションでは、各オブジェクトには
__proto__
のプロパティがあり、対応するコンストラクション関数のprototype
のプロパティを指します.Class
は、構造関数の構文糖として、prototype
属性と__proto__
属性を同時に有するため、2つの継承鎖が同時に存在する.__proto__
属性は、構造関数の継承を表し、常に親prototype
属性の__proto__
属性は、メソッドの継承を示す、常に親クラスのprototype
属性class A { }
class B extends A { }
B.__proto__ === A; // true
B.prototype.__proto__ === A.prototype; // true
上記のコードでは、サブクラス
B
の__proto__
属性は親クラスA
を指し、サブクラスB
のprototype
属性は親クラス__proto__
のA
属性を指す.Extendsの継承目標
prototype
キーワードの後には、複数のタイプの値を付けることができます.class B extends A {}
上のコードの
extends
は、A
の属性を持つ関数であれば、prototype
に継承されます.関数にはB
の属性(prototype
の関数を除く)があるため、Function.prototype
は任意の関数であってもよい.以下、3つの特殊な状況について議論する.
第1の特殊な場合、サブクラスは
A
クラスを継承する.class A extends Object {
}
A.__proto__ === Object; // true
A.prototype.__proto__ === Object.prototype; // true
この場合、
Object
は構造関数A
の複製であり、Object
の例はA
の例である.第2の特殊な状況では、継承は存在しません.
class A {}
A.__proto__ === Function.prototype; // true
A.prototype.__proto__ === Object.prototype; // true
この場合、
Object
はベースクラス(すなわち、継承は存在しない)として通常の関数であるため、A
を直接継承する.しかし、Funciton.prototype
が呼び出されると、空のオブジェクト(すなわち、A
のインスタンス)が返されるので、Object
は、コンストラクション関数(A.prototype.__proto__
)のObject
属性を指す.第3の特殊な場合、サブクラスは
prototype
を継承するclass A extends null {
}
A.__proto__ === Function.prototype; // true
A.prototype.__proto__ === undefined; // true
この状況は第2の状況と非常に似ている.
null
も一般的な関数なので、A
を直接継承します.ただし、Funciton.prototype
呼び出し後に返されるオブジェクトはメソッドを継承しないため、A
は__proto__
を指し、すなわち実質的に次のコードが実行される.class C extends null {
constructor() {
return Object.create(null);
}
}
Object.getPrototypeOf()
Function.prototype
メソッドは、子から親を取得するために使用することができる.Object.getPrototypeOf(A) === B;
したがって,この手法を用いて,あるクラスが別のクラスを継承しているか否かを判断することができる.
superキーワード
Object.getPrototypeOf
というキーワードは、2つの使い方があり、意味が違います.super
)、super(...args)
は親のコンストラクション関数super
またはsuper.prop
)、super.method()
は親を表す.なお、このときsuper
は、親インスタンスの属性およびメソッドを参照してもよいし、親の静的メソッドclass B extends A {
get m() {
return this._p * super._p;
}
set m() {
throw new Error(' ');
}
}
上記のコードでは、サブクラスは
super
キーワードを介して、親インスタンスのsuper
属性を呼び出す.オブジェクトは常に他のオブジェクトを継承するため、いずれかのオブジェクトで
_p
キーワードを使用できます.var obj = {
toString() {
return "MyObject: " + super.toString();
}
};
obj.toString(); // MyObject: [object Object]
生命は止まらず、振り回されて止まらない...I'm not a real coder, but i love it so much!