質問
同様の質問がたくさんあることは承知していますが、これに対する素晴らしい答えがたくさんあります。古典的な継承メソッドやクロージャメソッドなどを調べてみました。どういうわけか、私にとってこれらは多かれ少なかれ「ハック」メソッドであると考えています。これは実際には JavaScript が行うように設計されているものではないからです。(私が間違っている場合は、誰かが私を修正することを歓迎します)。OK、それが機能する限り、次のような古典的な継承パターンで満足します。
PARENTClass = function (basevar) { do something here; };
PARENTClass.prototype = { a: b, c: d}; // prototype is auto gen
// Inheritance goes here
CHILDClass = function (childvar) { do something; };
CHILDClass.prototype = new PARENTClass(*1); // Actual inheritance to the prototype statement
// Instance
CHILDInstance = new CHILDClass(whatever);
上記は、どういうわけか、JS の継承を理解しています。しかし、実装方法がわからないシナリオの 1 つは、オブジェクトの作成中 (つまり、コンストラクター内) に初期化を行い、新しいオブジェクトをすぐに使用できるようにしたい場合はどうなるかということです。問題に関する私の図はあまり明確ではないかもしれないので、次の C# 疑似を使用して、私が何をしたいのかを説明しましょう。
class PARENT {
public PARENT (basevar) { ... }
}
class CHILD : PARENT {
public CHILD (basevar) : PARENT (basevar) // constructor of child, and call parent constructor during construct.
{ ... }
}
何らかの理由で (init など)UI 要素)、それらをコンストラクターに入れるのが最善の方法のようです。誰もがそれを行う方法についてアイデアを持っています。
追伸:*1 に何を入れればいいのか分かりません。PS2:上記の状況は、jquery.inherit ライブラリで実行できることがわかりましたが、ライブラリを使用せずにそれを達成できるかどうか疑問に思っています。PS3:あるいは私の理解が間違っています。JavaScript は OOP を模倣することを目的としたものではないので (それが私がこれをハックと呼んでいる理由です)、これを実装するための「正しい」ロジックは何ですか。
解決
これは、次のようなのハックのではありません。
:ウィキペディアの場合などで定義されたJavaScriptは、試作した言語であり、それが言うように、..クラスが存在せず、行動の再利用(クラスベース言語の継承として知られている)のプロトタイプとして機能する既存のオブジェクトをクローニングするプロセスを介して行われる。
、クラスがJavaScriptで使用されていません。作成した各オブジェクトは、JavaScriptのObject
から降りています。 JavaScriptですべてのオブジェクトがprototype
オブジェクトがあり、オブジェクトのすべてのインスタンスは、あなたはそれらのオブジェクトのプロトタイプオブジェクトから「継承」メソッドとプロパティを作成します。詳細については、MDC プロトタイプのオブジェクト参照を見てみましょう。
これは、あなたがラインを呼び出すときます:
CHILDClass.prototype = new PARENTClass();
これはCHILDClass
オブジェクトは、クラスベースの言語に存在する継承の概念と同様の効果を作成PARENTClass
オブジェクトからそのプロトタイプオブジェクトにメソッドとプロパティを追加することを可能にします。 prototype
オブジェクトは、そのオブジェクトの作成したすべてのインスタンスに影響するため、これは親オブジェクトのメソッドとプロパティは、あなたの子オブジェクトのすべてのインスタンスに存在することができるようになります。
は、JavaScriptのcall
関数を使用します。これは、あなたがそれゆえ、彼らは親クラスのように設定されているものにあなたの子供のクラスでは、新たに試作したプロパティを設定し、子クラスのコンストラクタのコンテキストで親クラスのコンストラクタを呼び出すことができます。
また、その行は単に子クラスのプロトタイプオブジェクトへのメソッドとプロパティを追加するために使用されているので、あなたが*1
を指定したものを配置する必要はありません。しかし、心に留めて、それは親クラスのコンストラクタを呼び出すことなので、親クラスのコンストラクタの動作に必須である任意の引数がある場合には、JavaScriptエラーを回避するために、これらが存在していることを確認する必要があります。
他のヒント
は、手動でこのようなサブクラスのコンストラクタで親クラスのコンストラクタを呼び出すことができます:
CHILDClass = function (basevar) {
PARENTClass.call(this, basevar);
// do something;
};
ここでのトリックはあなたが別のオブジェクトのコンテキストでメソッドを呼び出すことができますcall
メソッドを使用しています。詳細はcall
するのマニュアルを参照してください。
JavaScriptを有しない内蔵の継承階層のサポート型エクステンションはプロパティがインスタンス間で共有される場合、オブジェクト自体またはそのプロトタイプに直接所望の機能を追加すること、すなわち、凝集を介して行われることになっている。
ありませんそれにも関わらず、JSは古典の継承を含む可能オブジェクト構築の他の形態を、実施作るのに十分強力である。
クローン機能を考えます - これは、「真」プロトタイプの継承ではなく、JavaScriptののbastardizationを追加するのに十分である - あなたのexampeは次のように実装することができます:
function ParentClass(baseVar) {
// do stuff
}
// don't overwrite the prototype object if you want to keep `constructor`
// see http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
ParentClass.prototype.a = 'b';
ParentClass.prototype.c = 'd';
function ChildClass(childVar) {
// call the super constructor
ParentClass.call(this, childVar);
}
// don't inherit from a ParentClass instance, but the actual prototype
ChildClass.prototype = clone(ParentClass.prototype);
ChildClass.prototype.e = 'f';
これは、クラスベースの継承のためにいくつかのシンタックスシュガーを追加することも可能です - 私自身の実装<のhref = "http://mercurial.intuxication.org/hg/js-hacks/raw-file/tip/class.js nofollowをnoreferrer "> "= relが" をここで見つけることができます。
上記の例は、次に読み出すことになる
var ParentClass = Class.extend({
constructor: function(baseVar) {
// do stuff
},
a: 'b',
c: 'd'
});
var ChildClass = ParentClass.extend({
e: 'f'
});
私はあなたが基本メソッドをオーバーライドしたり、基本コンストラクタまたはメンバーを呼び出すことができる「クラス様」の継承を提供して軽量なJavaScriptのOOPラッパを持っています。
あなたはこのようなあなたのクラスを定義します:
//Define the 'Cat' class
function Cat(catType, firstName, lastName)
{
//Call the 'Animal' constructor.
Cat.$baseNew.call(this, firstName, lastName);
this.catType = catType;
}
//Extend Animal, and Register the 'Cat' type.
Cat.extend(Animal, { type: 'Cat' }, {
hello: function(text)
{
return "meaoow: " + text;
},
getFullName: function()
{
//Call the base 'Animal' getFullName method.
return this.catType + ": " + Cat.$base.getFullName.call(this);
}
})
//It has a built-in type system that lets you do stuff like:
var cat = new Cat("ginger", "kitty", "kat");
Cat.getType() // "Cat"
cat.getBaseTypesAndSelf() // ["Cat","Animal","Class"]
cat.getType() // "Cat"
cat.isTypeOf(Animal.getType()) // "True"
var dynamicCat = Class.createNew("Cat", ["tab","fat","cat"])
dynamicCat.getBaseTypesAndSelf() // ["Cat","Animal","Class"]
dynamicCat.getFullName() // tab: fat cat
で入手可能なソースコード:クラス。 JS の
私はまた、JavaScriptで OOP の<についての私のブログの記事で詳細を持っています/ P>
あなたが目指している古典的なパターンの問題のいくつかについて言及したいと思いました。
- スーパークラスの参照変数は、基本的にすべてのインスタンスで静的変数として使用できます。たとえば、スーパーに var arr = [1,2,3] があり、instance_1.arr.push(4)、instance_2.arr.push(5) を実行すると、これらのインスタンスすべてが変更を「確認」します。
それで1を解決します。Zakas が「コンストラクターの盗用」と呼ぶ Ayman のソリューションでは、コンストラクターを 2 回呼び出すことになります。1 回はプロトタイプ用、もう 1 回はコンストラクターの盗用用です。解決策 - プロトタイプには、inheritPrototype のようなヘルパーを使用します (この投稿では、これの実装全体を示しました: 継承プロトタイプ メソッド FWIW、これは基本的にザカスの本の181ページとクロックフォードの研究を組み合わせたものです。
プライバシーはありません (ただし、これを取得するには Durable Object パターンのようなものを使用する必要があり、それはあなたが望んでいることではないかもしれません)
- オブジェクト定義は「ぶら下がった」ままになります。解決策 - プロトタイプの関数をチェックする if ステートメントを配置し、プロトタイプ リテラルを使用してプロトタイプを定義します。
これらすべての実行例が github にあります。
私にとって、その両方を真に理解することは、同じくらい困難でした。オブジェクトの作成と継承に関する Zakas と Crockford の書籍。また、いくつかの異なる JavaScript TDD フレームワークを試す必要もありました。そこで、TDD フレームワークと JavaScript オブジェクトの作成と継承の両方に関するエッセイを作成することにしました。実行中のコードと jspec テストが含まれています。リンクは次のとおりです:*私の GitHub オープンソース エッセイ/本