プロトタイプは最適化です。
jQueryライブラリをよく使用した例があります。 $('.someClass')
を使用してjQueryオブジェクトを取得するたびに、そのオブジェクトには数多くの「メソッド」があります。ライブラリには、オブジェクトを返すことでそれを実現できます。
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言語との比較です。
- インターフェース継承、どこ
implement
interface
クラスがインタフェースのすべてのメンバーのための独自の実装を提供するように、これらは、継承の2種類をサポートしています。
- インプリメンテーション
extend
class
は、いくつかのメソッドのデフォルトの実装を提供します。
JavaScriptでは、プロトタイプの継承はの実装継承の種類です。したがって、(C#またはJavaでは)基本クラスから派生してデフォルトの動作を取得し、オーバーライドを使用して小さな変更を加えた場合、JavaScriptではプロトタイプの継承が有効です。
しかし、C#またはJavaでインターフェイスを使用した場合、JavaScriptでは特定の言語機能は必要ありません。オブジェクトの各「タイプ」は、独自の定義を持っている場合、つまり、
var duck = {
quack: function() { ... }
};
duck.quack(); // we're satisfied it's a duck!
:明示的インターフェイスを表し、何かを宣言する必要、及びそのインタフェースを「実装」としてオブジェクトをマークする必要はありません"メソッド"の場合、プロトタイプから継承する価値はありません。その後、どのタイプのインスタンスをいくつ割り当てるかによって異なります。しかし、多くのモジュール設計では、特定のタイプのインスタンスが1つしかありません。
実際、it has been suggested by many people that implementation inheritance is evilです。つまり、型に共通の操作がいくつかある場合、基本/スーパークラスに入れられていない場合は明らかになりますが、オブジェクトを渡すモジュールの通常の関数として公開されているだけで、あなたはそれらを操作したい。
良い説明。プロトタイプを最適化することを考えているので、コードを改善するために常に使用できます。プロトタイプを使用することが意味をなさない場合や実際にパフォーマンスの低下を招くケースがあるかどうかは疑問です。 – opl
あなたのフォローアップでは、「あなたが各タイプをどれくらいのインスタンスに割り当てるかによって異なります」と言います。しかし、あなたが参照する例はプロトタイプを使用していません。インスタンスを割り振るという概念はどこにありますか(まだここでは「新しい」を使用していますか?)また、quackメソッドにパラメータがあったとします - duck.quack(param)を呼び出すたびに新しいオブジェクトがメモリに作成されます(パラメータがある場合とそうでない場合は無関係かもしれません)? – opl
** 1。**あるタイプのアヒルのインスタンスが多数存在する場合、 'quack'関数がプロトタイプになるようにサンプルを変更すると意味があります。インスタンスはリンクされています。 ** 2 ** **オブジェクトのリテラル構文 '{...}'はインスタンスを作成します(それには 'new'を使う必要はありません)。 ** 3。**任意の関数JSを呼び出すと、メモリに少なくとも1つのオブジェクトが作成されます。これは 'arguments'オブジェクトと呼ばれ、呼び出しで渡された引数を格納します:https://developer.mozilla.org/ja/JavaScript/Reference/functions_and_function_scope/arguments –