回答:
プロトタイプは最適化です。
それらを上手に使用する良い例は、jQueryライブラリーです。を使用してjQueryオブジェクトを取得するたびに$('.someClass')
、そのオブジェクトには数十の「メソッド」があります。ライブラリはオブジェクトを返すことでそれを実現できます:
return {
show: function() { ... },
hide: function() { ... },
css: function() { ... },
animate: function() { ... },
// etc...
};
しかし、それは、メモリ内のすべてのjQueryオブジェクトが、同じメソッドを何度も繰り返し含む数十の名前付きスロットを持つことを意味します。
代わりに、これらのメソッドはプロトタイプで定義され、すべてのjQueryオブジェクトはそのプロトタイプを「継承」して、実行時のコストをほとんどかけずにこれらすべてのメソッドを取得します。
jQueryが正しく機能するための非常に重要な部分の1つは、これがプログラマーから隠されていることです。ライブラリを使用するときに心配する必要があるものとしてではなく、純粋に最適化として扱われます。
JavaScriptの問題は、ネイキッドコンストラクター関数では、呼び出し元にプレフィックスを付けることを覚えておく必要があることですnew
。そうしないと、通常は機能しません。これには正当な理由はありません。jQueryは、通常の関数の背後にそのナンセンスを隠すことによってそれを正しく$
行います。そのため、オブジェクトの実装方法を気にする必要はありません。
指定したプロトタイプでオブジェクトを簡単に作成できるように、ECMAScript 5には標準関数が含まれていますObject.create
。それを大幅に簡略化したバージョンは次のようになります。
Object.create = function(prototype) {
var Type = function () {};
Type.prototype = prototype;
return new Type();
};
コンストラクター関数を作成し、それをで呼び出すという面倒な処理を行うだけnew
です。
いつプロトタイプを避けますか?
有用な比較は、JavaやC#などの一般的なOO言語との比較です。これらは2種類の継承をサポートします。
implement
するinterface
ようにします。extend
class
JavaScriptでは、プロトタイプ継承は一種の実装継承です。したがって、(C#またはJavaで)基本クラスから派生してデフォルトの動作を取得するような状況では、オーバーライドを介して小さな変更を加え、JavaScriptでプロトタイプの継承が理にかなっています。
ただし、C#またはJavaのインターフェイスを使用する状況では、JavaScriptに特定の言語機能は必要ありません。インターフェイスを表すものを明示的に宣言する必要はありません。また、オブジェクトをそのインターフェイスを「実装する」としてマークする必要もありません。
var duck = {
quack: function() { ... }
};
duck.quack(); // we're satisfied it's a duck!
言い換えると、オブジェクトの各「タイプ」に「メソッド」の独自の定義がある場合、プロトタイプから継承しても意味がありません。その後は、各タイプに割り当てるインスタンスの数によって異なります。しかし、多くのモジュール設計では、特定のタイプのインスタンスは1つしかありません。
実際、実装の継承は悪であることが多くの人から示唆されています。つまり、型にいくつかの一般的な操作がある場合、それらが基本/スーパークラスに入れられず、オブジェクトを渡すいくつかのモジュールで通常の関数として単に公開されている場合はおそらくより明確になりますあなたは彼らに働きかけたいのです。
quack
アヒルのインスタンスが多数ある場合は、多くのダックインスタンスがリンクされているプロトタイプに関数が含まれるように例を変更することは意味があることを意味しました。2.オブジェクトリテラル構文{ ... }
はインスタンスを作成します(これを使用new
する必要はありません)。3. JSは、少なくとも一つのオブジェクトがメモリ内に作成されるようにする任意の関数を呼び出す-それは呼ばれていますarguments
引数が呼び出しに渡されたオブジェクトを格納:developer.mozilla.org/en/JavaScript/Reference/...
オブジェクトの「非静的」メソッドを宣言する場合は、プロトタイプを使用する必要があります。
var myObject = function () {
};
myObject.prototype.getA = function (){
alert("A");
};
myObject.getB = function (){
alert("B");
};
myObject.getB(); // This works fine
myObject.getA(); // Error!
var myPrototypeCopy = new myObject();
myPrototypeCopy.getA(); // This works, too.
this
例のようにコンストラクタ関数内でメソッドを定義するだけで、オブジェクトの非静的メソッドを作成できますthis.getA = function(){alert("A")}
か?
組み込みprototype
オブジェクトを使用する1つの理由は、共通の機能を共有するオブジェクトを複数回複製する場合です。プロトタイプにメソッドをアタッチすることにより、new
インスタンスごとに作成される複製メソッドを節約できます。ただし、メソッドをにアタッチするとprototype
、すべてのインスタンスがそれらのメソッドにアクセスできます。
基本Car()
クラス/オブジェクトがあるとします。
function Car() {
// do some car stuff
}
次に、複数のCar()
インスタンスを作成します。
var volvo = new Car(),
saab = new Car();
これで、各車が運転、電源を入れる必要があることがわかりました。Car()
クラスに直接メソッドをアタッチする(作成されるインスタンスごとにメモリを消費する)代わりに、プロトタイプにメソッドをアタッチできます(メソッドのみを作成します)したがって、これらのメソッドへのアクセスをnew volvo
との両方に許可しますsaab
。
// just mapping for less typing
Car.fn = Car.prototype;
Car.fn.drive = function () {
console.log("they see me rollin'");
};
Car.fn.honk = function () {
console.log("HONK!!!");
}
volvo.honk();
// => HONK!!!
saab.drive();
// => they see me rollin'
Car.prototype = { ... }
ているように、を呼び出す前にを呼び出す必要があります。あなたの議論については、これはそれを行う正しい方法です:jsfiddle.net/Embnp。面白いのは、この質問に答えたことを覚えていない=)new Car()
特定の種類のオブジェクトの多数のコピーを作成し、それらすべてが共通の動作を共有する必要がある場合は、プロトタイプオブジェクトに関数を配置します。そうすることで、各関数のコピーを1つだけ持つことでメモリを節約できますが、それは最も単純な利点にすぎません。
プロトタイプオブジェクトのメソッドを変更するか、メソッドを追加すると、対応するタイプのすべてのインスタンスの性質が即座に変更されます。
今まさに、なぜあなたは、これらすべてのことを行うだろうと、主に独自のアプリケーション設計の関数であり、物事の種類は、あなたは、クライアント側のコードで行う必要があります。(まったく別の話は、サーバー内のコードです。そこでより大規模な "OO"コードを実行することを想像するのははるかに簡単です。)
クラスベースの用語で説明すると、Personはクラス、walk()はPrototypeメソッドです。つまり、walk()は、これを使用して新しいオブジェクトをインスタンス化した後でのみ存在します。
したがって、Person uが多くのユーザーを作成できるようなオブジェクトのコピーを作成する場合、メモリ内の各オブジェクトに対して同じ関数のコピーを共有/継承することでメモリを節約できるため、プロトタイプは優れたソリューションです。
一方、静的はそのようなシナリオではそれほど役に立ちません。
function Person(){
this.name = "anonymous";
}
// its instance method and can access objects data data
Person.prototype.walk = function(){
alert("person has started walking.");
}
// its like static method
Person.ProcessPerson = function(Person p){
alert("Persons name is = " + p.name);
}
var userOne = new Person();
var userTwo = new Person();
//Call instance methods
userOne.walk();
//Call static methods
Person.ProcessPerson(userTwo);
これにより、インスタンスメソッドのようになります。オブジェクトのアプローチは静的メソッドに似ています。
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript