純粋なJavaScriptを使用して継承を行う、これは私が通常行うことです。
function A() {}
A.prototype.run = function () {};
function B() {}
B.prototype = new A;
B.prototype.constructor = B;
コンストラクターに渡す引数がないため、新しいAには不満はありません。現在、コンストラクターに渡す引数がある場合に継承を行うための適切な方法がわかりません。例えば、
function A(x, y) {}
A.prototype.run = function () {};
function B(x, y) {}
B.prototype = new A;
B.prototype.constructor = B;
次のような任意の値を渡すことができます。
B.prototype = new A(null, null);
場合によっては、Aのコンストラクターでxとyを検証する必要があります。極端な場合には、xまたはyをチェックするときにエラーをスローする必要があります。次に、Bが新しいAを使用してAから継承する方法はありません。
助言がありますか?
ありがとう!
まあ、A
コンストラクターを実行せずにB.prototype
をA.prototype
から継承するオブジェクトにしたい場合は、考えられるすべての副作用を回避するために、ダミーコンストラクターを使用してそれ、例えば:
function tmp() {}
tmp.prototype = A.prototype;
B.prototype = new tmp();
B.prototype.constructor = B;
この新しいオブジェクトの作成のロジックをカプセル化する関数を作成できます。例:
function inherit(o) {
function F() {}; // Dummy constructor
F.prototype = o;
return new F();
}
//...
B.prototype = inherit(A.prototype);
B.prototype.constructor = B;
最新のブラウザを対象とする場合、ECMAScript 5 Object.create
メソッドを同じ目的で使用できます。
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
//..
問題は、B
のコンストラクターを呼び出すことができないため、A
のプロトタイプオブジェクトを簡単に作成できないことです。これは、_new B
_が実行される前はコンストラクタのパラメータが不明であるためです。 B
のプロトタイプにリンクするA
のプロトタイプを作成するには、ダミーのコンストラクター関数が必要です。
_B.prototype = (function(parent){
function protoCreator(){};
protoCreator.prototype = parent.prototype;
// Construct an object linking to A.prototype without calling constructor of A
return new protoCreator();
})(A);
_
B
のプロトタイプオブジェクトを設定したら、A
のコンストラクターでB
のコンストラクターを呼び出す必要があります。
_function B(x, y) {
// Replace arguments by an array with A's arguments in case A and B differ in parameters
A.apply(this, arguments);
}
_
これで、new B(x, y)
を呼び出してB
をインスタンス化できるようになります。
A
でのパラメーター検証を含む完全に同じものについては、 a jsFiddle を参照してください。
元のコードでは_B.prototype.constructor = B
_を設定しています。なぜあなたはこれをしているのか分かりません。 constructor
プロパティは、prototype
プロパティが担当する継承階層には影響しません。名前付きコンストラクタをconstructor
プロパティに含める場合は、コードを少し上から拡張する必要があります。
_// Create child's prototype – Without calling A
B.prototype = (function(parent, child){
function protoCreator(){
this.constructor = child.prototype.constructor
};
protoCreator.prototype = parent.prototype;
return new protoCreator();
})(A, B);
_
_B.prototype
_の最初の定義を使用すると、次の結果が得られます。
_var b = new B(4, 6);
b.constructor // A
console.info(b instanceof A); // true
console.info(b instanceof B); // true
_
拡張バージョン を使用すると、次のようになります。
_var b = new B(4, 6);
b.constructor // B
console.info(b instanceof A); // true
console.info(b instanceof B); // true
_
異なる出力の原因は、instanceof
がb
のプロトタイプチェーン全体を追跡し、_A.prototype
_または_B.prototype
_(他の呼び出し)。 _b.constructor
_プロトタイプは、インスタンスのプロトタイプを定義するために使用された関数を指します。なぜprotoCreator
を指さないのか疑問に思う場合、これは、そのプロトタイプが_A.prototype
_の作成中に_B.prototype
_で上書きされたためです。 更新された例 に示されている拡張定義は、このconstructor
プロパティを修正して、より適切な(おそらくより期待されるため)関数を指すようにします。
日常的に使用する場合は、インスタンスのconstructor
プロパティを完全に使用するという考えを破棄することをお勧めします。結果がより予測可能/期待されるため、代わりにinstanceof
を使用してください。
これは古いトピックですが、とにかく返答するつもりだと思いました。それを行う2つの方法:
Pseudo Classicalの方法が最も一般的ですが、親コンストラクターを子コンストラクターで一度、プロトタイプを継承する間に一度呼び出す必要があるため、欠点があります。さらに、子のプロトタイプには親コンストラクターのすべてのプロパティが含まれ、子コンストラクターが呼び出されたときに上書きされます。私の個人的な選択はプロトタイプの継承です。
function A(x, y) {}
A.prototype.run = function () {};
function B(x, y) {
A.call(this,x,y);
}
B.prototype = new A();
B.prototype.constructor = B;
function A(x, y) {}
A.prototype.run = function () {};
function B(x, y) {
A.call(this,x,y);
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
このことを考慮:
function B( x, y ) {
var b = Object.create( new A( x, y ) );
// augment b with properties or methods if you want to
return b;
}
その後
var b = new B( 12, 13 );
これで、b
はA
のインスタンスから継承され、A.prototype
から継承されます。
ライブデモ:http://jsfiddle.net/BfFkU/
Object.create
はIE8には実装されていませんが、手動で簡単に実装できます。
if ( !Object.create ) {
Object.create = function ( o ) {
function F() {}
F.prototype = o;
return new F();
};
}
これは、条件付きコメントを介してIE8以下でのみロードされるie8.js
ファイル内に配置できます。