Ответ 1
Вы никогда не должны расширять Object.prototype
. Это намного больше, чем разрыв jQuery; он полностью разрушает функцию "объект-как-хэш-таблицы" Javascript. Не делайте этого.
Вы можете спросить Джона Ресига, и он скажет вам то же самое.
Я добавил простой файл .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 - undefined.
Хотя очевидно, что что-то, что я просто не обволакиваю головой прототипом, я с трудом могу понять, что это такое.
Чтобы быть ясным, я не ищу обходного пути, у меня это обработано... то, что я ищу, является ответом на Почему?. Почему добавление функции в Object.prototype
прерывает этот бит кода?
Вы никогда не должны расширять Object.prototype
. Это намного больше, чем разрыв jQuery; он полностью разрушает функцию "объект-как-хэш-таблицы" Javascript. Не делайте этого.
Вы можете спросить Джона Ресига, и он скажет вам то же самое.
Если это просто случай перебора для... в цикле, не можете ли вы использовать Object.defineProperty, чтобы добавить свой fn, не делая его перечислимым?
Итак:
Object.defineProperty(Object.prototype, "foo", {
value: function() {
// do stuff
},
enumerable : false
});
Кажется, работает для меня. Будет ли это считаться плохой формой?
Я согласен, добавив что-то к 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)
, и он читается как рассылка.
Но, как правило, избегайте изменения любого из крупных прототипов.
Я ударил головой по этой проблеме, поскольку я хотел реализовать "реальную" ориентацию объекта во всех моих объектах, например:
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. Просто убедитесь, что каждый из циклов .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
}}