1. ホーム
  2. javascript

[解決済み] Javascriptでプロトタイプを使用するタイミング

2022-12-31 06:17:47

質問

jsでプロトタイプメソッドを使用することが適切な場合について理解したいです。 それらは常に使用されるべきですか?それとも、それらを使用することが好ましくない、および/またはパフォーマンス上のペナルティを発生させるケースがあるのでしょうか?

jsの名前空間に関する一般的なメソッドについてこのサイトを検索してみると、ほとんどがプロトタイプに基づかない実装を使用しているようです。

クラスベースの言語から来た私にとって、プロトタイプはクラスと同じであり、私が言及した名前空間の実装は静的メソッドのようであると考え、類似点を描こうとしないのは難しいことです。

どのように解決するのですか?

プロトタイプは 最適化 .

これらをうまく使っている好例が、jQueryライブラリです。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言語と比較するのが便利です。これらは2種類の継承をサポートしています。

  • インターフェース を継承し、そこで implement アン interface のように、クラスがインターフェースの各メンバーに対して独自の実装を提供するようにします。
  • 実装 を継承し、そこで extend a class で、いくつかのメソッドのデフォルトの実装を提供します。

JavaScriptでは、プロトタイプ継承は一種の の実装です。 継承の一種です。つまり、(C# や Java では) デフォルトの振る舞いを得るために基底クラスから派生し、それをオーバーライドして小さな変更を加えるような状況において、JavaScript ではプロトタイプ継承が意味を持ちます。

しかし、C#やJavaでインターフェイスを使っていたような状況であれば、JavaScriptでは特に言語的な特徴は必要ないでしょう。インターフェースを表すものを明示的に宣言する必要はありませんし、オブジェクトにそのインターフェースを実装していることを示す "implementation"をつける必要もありません。

var duck = {
    quack: function() { ... }
};

duck.quack(); // we're satisfied it's a duck!

つまり、オブジェクトの "type" それぞれが "methods" を独自に定義しているならば、プロトタイプを継承する価値はないのです。その後は、各タイプのインスタンスをいくつ割り当てるかによります。しかし、多くのモジュール設計では、与えられた型のインスタンスは1つだけです。

そして実際 は、実装継承は悪であると多くの人々から言われています。 . つまり、ある型に共通する操作がある場合、それを基底/上位クラスではなく、普通の関数としてモジュールで公開し、そこに操作したいオブジェクトを渡すようにすれば、より明確になるのではないでしょうか。