JavaScript のクラス継承に関しては、プロトタイプ チェーンと切り離すことができませんが、プロトタイプ チェーンのみを介して実装された継承には多くの欠陥があります。
パラメータなしのクラス継承に関する問題
まず、A を継承して B を実装するサンプル コードを見てみましょう:
関数 A() {
}
A.prototype.a1 = function() { };
関数 B() {
}
B.prototype = new A();
B.prototype.b1 = function() { };
var b = new B();
alert(b.constructor == A) // true
alert(b.constructor == B); // false
このコードの主な問題は次のとおりです:
1. A を B のプロトタイプとしてインスタンス化する必要があります。このとき、A のコンストラクターが実行されます。しかし、オブジェクト指向の規則によれば、B をインスタンス化する前に、B とその親クラス A のコンストラクターを実行すべきではありません。
2. B のプロトタイプを変更し、b.constructor が B ではなく A になりました。
パラメータクラスの継承に問題があります
A と B の両方に 2 つの文字列パラメーター s1 と s2 があるとします。A は、s1 と s2 をパラメーターとして使用して A を直接呼び出します。
関数 A(s1, s2) {
this.totalLength = s1.length s2.length;
}
A.prototype.a1 = function() {
};
関数 B(s1, s2) {
}
B.prototype = new A();
B.prototype.b1 = function() {
};
new B("ab", "123");
ご覧のとおり、このコードでは s1 と s2 を A に渡す方法がなく、A を B のプロトタイプとしてインスタンス化するときにパラメーターがないため、例外が発生します。
s1 は未定義です
解決策
s1 と s2 のスコープは B にのみあります。それらを A に転送したい場合は、B でのみ操作できます。これは、関数の apply メソッドを使用して実現できます。
関数 B(s1, s2) {
A.apply(this, argument);
アラート(this.totalLength);
}
次の問題は、A のメソッドを B のプロトタイプに追加する方法です。これは難しいことではありません。A.prototype をトラバースしてメソッドを B.prototype にコピーするだけです。同じ名前のメソッドの場合、サブクラスが当然優先される (オーバーロード) ため、オーバーライドできないことに注意してください。
if (!B.prototype[m]) { // 親クラスはサブクラスのメソッドをオーバーライドできません
B.プロトタイプ[m] = A.プロトタイプ[m];
}
}
追記
C# や Java などの高級言語が多重継承を放棄していることを考慮して、この記事では単一継承についてのみ説明します。この記事で説明する継承メソッドも jRaiser の拡張機能として作成され、後日リリースされる予定です。