Вопрос

Я добавил простой .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 сломать этот фрагмент кода?

Это было полезно?

Решение

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

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

Другие советы

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

Итак:

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

Кажется, у меня это работает.Будет ли это по-прежнему считаться дурным тоном?

Я согласен, добавив кое-что к 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) и это читается как приговор.

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

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

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.

Я сомневаюсь, что добавление функции в 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
}}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top