web-dev-qa-db-ja.com

JavascriptでオブジェクトをプロトタイピングするとjQueryが壊れますか?

ObjectおよびArrayプロトタイプに追加されたかなりありふれた共通タスクの種類の関数を含む単純な.jsファイルをページに追加しました。

試行錯誤の結果、Object.prototypeに関数を追加すると、その名前や機能に関係なく、jQueryでJavascriptエラーが発生することがわかりました。

犯人?

Object.prototype.foo = function() {
    /*do nothing and break jQuery*/
};

Attr:function {}宣言で、jquery-1.3.2.jsの1056行目にあるエラー:

/*Object doesn't support this property or method*/
name = name.replace(/-([a-z])/ig, function(all, letter) {
            return letter.toUpperCase();
        });

どうやらG.replaceは未定義です。

プロトタイピングで頭を包み込んでいないことがあるのは明らかですが、それが何であるかを無残に理解することに失敗しています。

明確にするために、私は回避策を探していません、私はそれを処理しました...私が探しているのはなぜ?への答えです。 Object.prototypeに関数を追加すると、このコードが壊れてしまうのはなぜですか?

35
Ben Lesh

Object.prototypeを拡張しないでください。 jQueryを壊すだけではありません。これは、Javascriptの「ハッシュテーブルとしてのオブジェクト」機能を完全に破壊します。それをしないでください。

あなたはジョン・レシグに尋ねることができます、そして彼はあなたに 同じこと を言うでしょう。

20
Josh Stodola

単にfor ... inループを台無しにする場合は、Object.definePropertyを使用して、列挙可能にせずにfnを追加できませんか?

そう:

Object.defineProperty(Object.prototype, "foo", { 
    value: function() {
        // do stuff
    },
    enumerable : false
});

私のために働くようです。これはまだ悪い形と見なされますか?

42
nicholas

同意します。_Object.prototype_に何かを追加するには注意が必要であり、避ける必要があります。次のような他の解決策を探してください。

オブジェクトに追加し、必要に応じてcallまたはapplyを使用してアクセスします。例えば:

_Object.foo = function () { return this.whatever()}
_

次に、次の方法でオブジェクトに対してそれを呼び出します。

_Object.foo.call(Objname);  // this invokes the function as though it were a
                           // method of Objname.  That is, its like Objname.foo()
_

楽しみのために、以下を追加することができます(はい、私はそれが少し危険であることを知っています...):

_Function.using = Function.call; // syntactic sugar
_

これでObject.foo.using(Objname)と書くことができ、それは文のように読めます。

ただし、原則として、大きなプロトタイプを変更しないでください。

5
davehamptonusa

次のように、すべてのオブジェクトに「実際の」オブジェクト指向を実装したかったので、この問題に頭を悩ませました。

interface Object
{
    GetType: () => string;
    ToString: () => string;
    GetHashcode: () => number;
    Equals: (obj: any) => boolean;
}

Object.prototypeはJQueryを壊すので、definePropertyを利用するためにデフォルトで上記のソリューションを使用しましたが、それは引数を取りません。

幸いなことに、definePropertyにハッキングして、実際にパラメーターを受け入れることができます。これが私の実装です:

Object.defineProperty(Object.prototype, "Equals",
    {
        value: function (obj: any)
        {
            return obj == null && this == null
                    ? true
                    : obj != null && this == null
                        ? false
                        : obj == null && this != null
                            ? false
                            : this.GetHashcode() == obj.GetHashcode();
        },
        enumerable: false
    });

これは機能し、JQueryと衝突しません。

1
Miguel