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


15

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


1
一つのことはfor(var ... in ...)、プロトタイプ関数も渡されるため、ループがめちゃくちゃになることです。
pimvdb

4
「酷く懲らされた」、本当に?!良い神、男:]大丈夫ですか?
pixelbobby

回答:


12

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

要約すれば:

仕様の欠如

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

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

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

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

衝突の可能性

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

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

ある種のプレフィックス戦略を採用すると、問題を軽減できます。ただし、おそらく余分なノイズも発生します。

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

[...] IE 6、7、Safari 2.xなどの要素拡張機能をサポートしていないブラウザには、手動のオブジェクト拡張機能が必要です。問題は、手動での拡張が遅く、不便で、拡張できないことです。

[...]要素の拡張を開始すると、ライブラリAPIはおそらく拡張要素をどこにでも返す必要があります。その結果、$$などのクエリメソッドは、クエリ内のすべての要素を拡張することになります。

IE DOMは混乱です

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

おまけ:ブラウザのバグ


9

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

jQueryアプローチでは、を見る$.foo(...)と、fooメソッドの名前空間により、何をするのかわからない場合にその定義/ドキュメントの場所が明らかになります。


メソッドがどこから来たのかを見つけることは、読者にとって非常に重要です。jQueryは、Webコードを読み始めて、それが何であるかまだわからないときに検索が難しいので、jQueryが良い例だとは本当に思いませんが。
サイモンフェルトマン

4

基本的な問題は次のとおりです:プロトタイプを互換性のない方法で拡張したり、一般的なメソッドを拡張して異なる結果を生成する(これはfor...inJavaScriptの特定の問題です)ため、依存するコードを引き起こす2つのツールがある場合彼らの通常の行動を破る?

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

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


1

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


1

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

  • 潜在的な衝突:両方が同じプロトタイプで同じプロパティを定義する異なるソースからの2つのコード
  • 副作用:延びるArray.prototype又はObject.prototypeノックオンように列挙されている拡張メソッド追加するなどの効果、有することができ、for...inループ

DOMプロトタイプの拡張に関しては、上記の潜在的な衝突の議論が依然として適用されます。さらに、DOMノードはホストオブジェクトであるため、ネイティブJavaScriptオブジェクトの通常のルールの対象にはなりません。彼らは本質的に好きなことをすることができ、賢明なプロトタイプオブジェクトを提供したり、余分な(「エクスパンド」)プロパティを許可する義務もありません。特定の演習でIEこの権利、DOMはIE 9の前にオブジェクトのための何のプロトタイプを提供していないと、さまざまなDOMオブジェクトのプロパティに関するさまざまなweirdnessesを持っ(あなたが一般的に何のセットを提供する要素にOK割り当てのプロパティ、しているもののdocument.expandofalse。)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.