6

JavaScriptの性質上、ネイティブオブジェクトを完全に書き直すことができます。そうすることで本当の危険があるかどうか知りたいです!

ネイティブJavaScriptオブジェクトの例を次に示します

Object
Function
Number
String
Boolean
Math
RegExp
Array

これらをJava(および他のいくつかのOOP言語)で見られるのと同様のパターンに従ってモデル化し、Objectが一連の基本関数を定義し、他の各オブジェクトがそれを継承するとします(これは明示的に行う必要があります)すべてが自然にオブジェクトから派生するJavaとは異なり、ユーザーによって定義されます)

例:

Object = null;
function Object() {
   Object.prototype.equals = function(other) {
      return this === other;
   }

   Object.prototype.toString = function() {
      return "Object";
   }

   Object.equals = function(objA, objB) {
      return objA === objB;
   }
}

Boolean = null;
function Boolean() {
}
extend(Boolean, Object);  // Assume extend is an inheritance mechanism

Foo = null;
function Foo() {
   Foo.prototype.bar = function() {
      return "Foo.bar";
   }
}

extend(Foo, Object);

このシナリオでは、ObjectとBooleanに新しい実装が追加されました。この点で、何が起こりそうですか?私は物事をさらに先に壊す可能性がありますか?

編集:

MooToolsやPrototypeなどのフレームワークがこれに似たアプローチをしていることをどこかで読みましたが、これは正しいですか?

4

4 に答える 4

4

そのような組み込みクラスにモンキーパッチを適用することは、物議を醸すトピックです。私は個人的に2つの理由でそれをするのが好きではありません:

  1. 組み込みクラスはグローバルスコープです。これは、2つの異なるモジュールが同じ名前のメソッドをグローバルクラスに追加しようとすると、それらが競合し、微妙なバグが発生することを意味します。さらに微妙なことに、ブラウザの将来のバージョンが同じ名前のメソッドを実装することを決定した場合、あなたも問題を抱えています。

  2. 一般的なクラスのプロトタイプに何かを追加すると、hasOwnPropertyチェックなしでfor-inループを使用するコードが壊れる可能性があります(for-inはforeachループのように見えるため、JSを初めて使用する人はオブジェクトや配列に対してそれを行うことがよくあります)。使用するコードがfor-inループを安全に使用していることを100%確信できない場合は、Object.prototypeにモンキーパッチを適用すると問題が発生する可能性があります。

とはいえ、モンキーパッチの組み込みが受け入れられる状況が1つあります。それは、古いブラウザーに新しいブラウザーの機能を追加することです(たとえば、配列のforEachメソッドなど)。この場合、将来のブラウザバージョンとの競合を回避し、驚かされる可能性はほとんどありません。しかし、それでも、自分でコーディングするのではなく、サードパーティのシムを使用することをお勧めします。これは、正しく理解するのが難しいトリッキーなコーナーケースが多いためです。

于 2013-01-08T19:23:42.733 に答える
1

ここにはある程度の好みがありますが、私の個人的な見解は、この種のものは巨大な手に負えない混乱になる可能性があるということです。

たとえば、AとBの2つのプロジェクトから始めます。これらのプロジェクトはそれぞれ、Stringにあらゆる種類の非常に便利で流暢なメソッドを実装することを決定します。

プロジェクトAは、文字列の長さがゼロまたは空白のみの場合に返さStringれる関数が必要であると判断しました。isEmptytrue

プロジェクトBは、文字列の長さがゼロの場合に返される関数と、文字列の長さがゼロまたは空白のみの場合に返される関数がString必要であると判断しました。isEmptytrueisEmptyOrWhitespacetrue

これで、プロジェクトAのコードとプロジェクトBのコードを使用したいプロジェクトができました。どちらもカス​​タム関数を多用していisEmptyます。2つにうまく参加するチャンスはありますか?おそらくそうではありません。あなたは、いわばクラスター配置にあります。

これはすべてC#の拡張メソッドとは大きく異なります。拡張メソッドを取得するには、少なくとも含まれている静的クラスの名前空間をインポートする必要があり、実行時の競合はなく、同じプロジェクト内のAとBから合理的に消費される可能性があります。拡張名前空間をインポートしなかったため(まさにこの理由で、拡張クラスを別の名前空間に配置する先見性があることを期待しています)。

于 2013-01-08T19:08:00.347 に答える
0

これらの線に沿って私が知っているJSの最悪のケースはですundefined。あなたはそれを定義することができます。

あなたはundefined = 'blah';....のようなことをすることが許されています。その時点で、あなたはもはや頼ることができませんif(x === undefined)。これは、コードの他の場所(または、もちろん、使用している可能性のあるサードパーティのライブラリ)で何かを簡単に壊す可能性があります。

これは完全に厄介ですが、組み込みオブジェクトを任意に上書きすることの間違いなく危険性を示しています。

参照:http ://wtfjs.com/2010/02/15/undefined-is-mutable

もう少し正気の例として、Sahiブラウザテストツールを取り上げます。このツールを使用すると、ブラウザがサイトをテストするための自動スクリプトを作成できます。(セレンに似ています)。これを行う際の問題の1つは、サイトでalert()またはを使用している場合confirm()、ユーザー入力を待機している間、スクリプトの実行が停止することです。Sahiは、これらの関数を独自のスタブ関数で上書きすることでこれを回避します。

于 2013-01-08T17:31:41.857 に答える
0

固有のオブジェクトのデフォルトの動作をオーバーライドすることは避けます。何度か噛まれましたが、他の人は元気でした。例として見ることができるライブラリはSugar.jsです。一部の人々が愛する素晴らしいライブラリですが、私は一般的に、あなたがしていることなど、既存のJavScriptオブジェクトの動作を拡張するという理由だけでそれを避けています。

しかし、これは純粋に意見とスタイルであることがわかると思います。

于 2013-01-08T18:40:44.187 に答える