継承の方法
ECMAScript には継承を実装する方法が複数あります。これは、JavaScript の継承メカニズムが明示的に指定されておらず、模倣によって実装されているためです。これは、継承の詳細すべてがインタープリターによって完全に処理されるわけではないことを意味します。開発者には、自分にとって最適な継承方法を決定する権利があります。最も原始的な継承実装方法はオブジェクト偽装です。これを以下に紹介します。
オブジェクトの偽装
継承を実装するためのオブジェクトの偽装の中核は、実際には関数環境での this キーワードの使用に依存します。原理は次のとおりです。コンストラクターは this キーワードを使用して、すべてのプロパティとメソッドに値を割り当てます (つまり、クラス宣言のコンストラクター メソッドを使用します)。コンストラクターは単なる関数であるため、ClassA コンストラクターを ClassB のメソッドにして呼び出すことができます。 ClassB は、ClassA のコンストラクターで定義されたプロパティとメソッドを受け取ります。たとえば、ClassA と ClassB を次のように定義します。
function ClassA(sColor) {
this.color = sColor;
this.sayColor = function () {
alert(this.color);
};
}
function ClassB(sColor) {
}
キーワード this は、コンストラクターによって現在作成されているオブジェクトを参照します。ただし、このメソッドでは、this はそれが属するオブジェクトを指します。原則は、ClassA をコンストラクターとしてではなく、通常の関数として使用して継承メカニズムを確立することです。継承メカニズムは、次のようにコンストラクター ClassB を使用して実装できます。
function ClassB (sColor) {
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;
}
このコードでは、ClassA にメソッド newMethod が割り当てられています (関数名はそれへの単なるポインターであることに注意してください)。次にメソッドが呼び出され、ClassB コンストラクターのパラメーター sColor が渡されます。コードの最後の行は ClassA への参照を削除し、今後呼び出すことができないようにします。
すべての新しいプロパティと新しいメソッドは、新しいメソッドのコード行を削除した後に定義する必要があります。それ以外の場合、スーパー クラスの関連するプロパティとメソッドがオーバーライドされる可能性があります:
function ClassB(sColor, sName) {
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
前のコードが有効であることを証明するには、次の例を実行します:
var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor(); //「青」を出力
objB.sayColor(); //「赤」を出力
objB.sayName() //「ジョン」を出力
オブジェクトの偽装多重継承を実現できます
興味深いことに、オブジェクトの偽装は多重継承をサポートできます。たとえば、2 つのクラス ClassX と ClassY があり、ClassZ がこれら 2 つのクラスを継承したい場合、次のコードを使用できます:
function ClassZ() {
this.newMethod = ClassX;
this.newMethod();
delete this.newMethod;
this.newMethod = ClassY;
this.newMethod();
delete this.newMethod;
}
2 つのクラスがある場合、ここには欠点があります。 ClassX ClassY と同じ名前のプロパティまたはメソッドの場合、ClassY の優先順位が高くなります。後のクラスから継承しているためです。この小さな問題は別として、オブジェクトの偽装を使用して複数の継承メカニズムを実装するのは簡単です。
この継承メソッドの人気により、ECMAScript の 3 番目のバージョンでは、Function オブジェクトに call() と apply() という 2 つのメソッドが追加されました。その後、継承を実装するための多くの派生メソッドが実際に call() と apply() に基づいて実装されました。