web-dev-qa-db-ja.com

DOM /組み込みオブジェクトのプロトタイプを拡張することはなぜ悪い考えなのですか?

組み込みプロトタイプの拡張がJS開発者コミュニティで非常に厳しく非難されている理由についての明確な答えを探しています。私はしばらくの間、Prototype JSフレームワークを使用しており、[1,2,3].each(doStuff)を実行することは、$.each([1,2,3], doStuff)よりもはるかにエレガントに思えます。それが「名前空間汚染」を引き起こすことは知っていますが、それがなぜ悪いことだと考えられているのか、私にはまだわかりません。また、組み込みプロトタイプの拡張に関連する実際のパフォーマンスの低下はありますか?ありがとう!

15
lxe

この記事 を読むことをお勧めします。これは、Prototypeに関しても、オブジェクトの拡張が悪い考えである理由をかなりよく説明していると思います。

要約すれば:

仕様の欠如

「プロトタイプオブジェクト」の公開は、仕様の一部ではありません。 [...]実装がDOM Level 2に完全に準拠するために、これらのグローバルNode、Element、HTMLElementなどのオブジェクトを公開する必要はありません。

ホストオブジェクトにはルールがありません

DOMオブジェクトはホストオブジェクトです[...]ホストオブジェクトは、実装に依存する動作でこれらの内部メソッドを実装する場合があります。または、ホストオブジェクトが一部の内部メソッドのみを実装し、他の内部メソッドを実装しない場合もあります。

[...]内部メソッドの動作は実装に依存します。 [...]定義により、予測できない、完全に不安定な方法で動作することが許可されている何かを使用しています。

衝突の可能性

現在使用されている環境が膨大であることを考えると、特定のプロパティが一部のDOMの一部でないかどうかを判断することは不可能になります。 [...]

すべての名前付きフォームコントロールは、プロトタイプチェーンを通じて継承されたプロパティをシャドウします。フォーム要素での衝突や予期しないエラーの可能性はさらに高くなります。

なんらかの接頭辞戦略を採用すると、問題を軽減できます。しかし、おそらく余分なノイズももたらします。

パフォーマンスのオーバーヘッド

[...] IE 6、7、Safari 2.xなど)のような要素拡張をサポートしていないブラウザは、手動のオブジェクト拡張を必要とします。問題は、手動の拡張が遅いことです。 、不便で、スケーリングされません。

[...]要素の拡張を開始すると、ほとんどの場合、ライブラリAPIは拡張された要素をどこにでも返す必要があります。その結果、$$のようなクエリメソッドは、クエリ内のすべての要素を拡張することになります。

IE DOMは混乱している

前のセクションで示したように、手動のDOM拡張機能は混乱します。ただし、IE=の手動DOM拡張はさらに悪い[...]

ボーナス:ブラウザのバグ

12
Jose Faeti

もう1つの理由は、コードの可読性/保守性です。別の開発者(特に初心者)が私のコードを読んでいて、[0, 1, 2].foo(...)を見つけた場合、彼らはfooメソッドが何であるか、またはそのドキュメント/ソースの場所を知らない可能性があります。 fooは、prototype.js、使用中の別のライブラリ、または別のファイルの私のコードの他の部分によって追加された言語の拡張ですか、それとも彼らが知らなかったネイティブJavaScriptメソッドですか?彼らはそれを探す必要があり、すぐに見つけられない可能性があります(または、競合がある場合、適切なものを見つけられない可能性があります)。

JQueryアプローチでは、$.foo(...)が表示される場合、fooメソッドの名前空間により、何が行われるかわからない場合にfooメソッドの名前空間により、定義/ドキュメントの場所が明確になります。

9
Bruce Harris

基本的な問題は次のとおりです。プロトタイプを互換性のない方法で拡張する2つのツールがある場合、または一般に呼び出されるメソッドを拡張して異なる結果が得られるようにツールを拡張するとどうなりますか(これはJavaScriptのfor...inの特定の問題です)。したがって、通常の動作に依存するコードが壊れる原因になりますか?

基本的には、グローバル変数を誤って使用する場合と同じ問題です。それ自体、おそらく悪いことは何も起こりません。しかし、見かけ上分離している2つのコードが突然互いに踏み込んだ場合、問題が発生しやすくなります(その場合、デバッグするのは面倒です)。

確かに、prototype.jsは非常によく知られており、ほとんどのツールがそれを回避します。同様に、ベースプロトタイプを拡張するのが正しい場合があると私は確信しています。ただし、注意してアプローチする必要があります。

4
Luke

これが本当に問題であるかどうかはわかりませんが、以前のバージョンのInternet Explorerでの私の経験では、特定のビルドインタイプを拡張することさえできなかったことがあります。

1
Jan-Peter Vos

ここには2つの個別の問題があります。 1つは組み込みプロトタイプの一般的な拡張で、もう1つはDOMプロトタイプの拡張です。組み込みプロトタイプの拡張に対する反対論:

  • 潜在的な衝突:異なるソースからの2つのコードが両方とも同じプロトタイプの同じプロパティを定義している
  • 副作用:Array.prototypeまたはObject.prototypeを拡張すると、for...inループで列挙されている拡張メソッドを追加するなどのノックオン効果が生じる可能性があります。

DOMプロトタイプの拡張に関しては、上記の潜在的な衝突の引数が引き続き適用されます。さらに、DOMノードはホストオブジェクトであるため、ネイティブJavaScriptオブジェクトの通常のルールは適用されません。それらは基本的に好きなことを行うことができ、賢明なプロトタイプオブジェクトを提供したり、追加の(「expando」)プロパティを許可する義務もありません。 IEは特にこの権利を行使し、IE 9の前にDOMオブジェクトのプロトタイプを提供せず、さまざまなDOMオブジェクトのプロパティについてさまざまな奇妙さを持っています(ただし、一般的にdocument.expandofalseに設定しない限り、要素にプロパティを割り当ててもかまいません。)

1
Tim Down