Прототипирование объекта в Javascript ломает jQuery? - PullRequest
35 голосов
/ 01 декабря 2009

Я добавил на свою страницу простой файл .js, в котором есть несколько довольно простых функций общего назначения, добавленных к прототипам Object и Array.

Методом проб и ошибок я выяснил, что добавление любой функции к Object.prototype независимо от ее имени и от того, что она делает, вызывает ошибки Javascript в jQuery:

Виновник?

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

Ошибка, я получаю строку 1056 из jquery-1.3.2.js, в attr: function {} объявление:

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

Видимо G.replace не определено.

Хотя очевидно, что есть кое-что, что я просто не заворачиваю в голову с прототипированием, я с треском проваливаюсь, чтобы понять, что это такое.

Чтобы было ясно, я не ищу обходной путь, я справился с этим ... то, что я ищу, - это ответ на Почему? . Почему добавление функции к Object.prototype нарушает этот бит кода?

Ответы [ 5 ]

41 голосов
/ 05 мая 2011

Если это просто случай путаницы в ... циклах, разве вы не можете использовать Object.defineProperty, чтобы добавить свой fn, не делая его перечисляемым?

Итак:

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

Кажется, работает на меня. Будет ли это все еще считаться плохой формой?

20 голосов
/ 01 декабря 2009

Вы никогда не должны расширять Object.prototype. Это гораздо больше, чем просто сломать jQuery; это полностью нарушает функцию «объект-как-хеш-таблицы» в Javascript. Не делай этого.

Вы можете спросить Джона Резига, и он скажет вам то же самое .

5 голосов
/ 13 марта 2010

Согласен, добавление чего-либо к Object.prototype требует осторожности и его следует избегать. Ищите другие решения, такие как:

Добавление его в Object и последующий доступ к нему с помощью 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), и это будет выглядеть как сторож.

Но, как правило, держитесь подальше от изменения любого из больших прототипов.

1 голос
/ 24 февраля 2016

Я ударился головой об эту проблему, так как хотел реализовать «реальную» ориентацию объекта во всех моих объектах, например:

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.

0 голосов
/ 01 декабря 2009

Я сомневаюсь, что добавление функции в Object.prototype напрямую нарушает работу jQuery. Просто убедитесь, что каждый цикл for..in, который вы имеете на своем сайте, обернут в проверку hasOwnProperty, поскольку вы добавляете функцию глобально, и результат ее перебора может быть непредсказуемым:

Object.prototype.foo = function() {};    
var myObject = {m1: "one", m2: "two" };

for(var i in myObject) { if(myObject.hasOwnProperty(i)) {
   // Do stuff... but not to Object.prototype.foo
}}
...