2009-06-04 5 views
32

Я работал над приложением asp.net с поддержкой AJAX. Я только добавил некоторые методы Array.prototype какДобавление пользовательских функций в Array.prototype

Array.prototype.doSomething = function(){ 
    ... 
} 

Это решение работает для меня, причем код повторного использования в «красивой» способом.

Но когда я протестировал его, работая со всей страницей, у меня были проблемы. У нас были некоторые пользовательские расширения ajax, и они начали вести себя как неожиданное: некоторые элементы управления отображали «неопределенные» вокруг своего содержимого или значения ,

Что может быть причиной этого? Я что-то пропустил для модификации прототипа стандартных объектов?

Примечание: Я уверен, что ошибка начинается, когда я модифицирую прототип для массива. Он должен быть совместим только с IE.

ответ

33

Модификация встроенных прототипов объектов может быть плохой идеей в целом, поскольку она всегда может столкнуться с другим кодом на той же странице.

В случае прототипа объекта Array это особенно плохая идея, поскольку он может помешать любому фрагменту кода, который выполняет итерации над элементами любого массива, например, с for .. in.

Чтобы проиллюстрировать на примере (заимствованные из here):

Array.prototype.foo = 1; 

// somewhere deep in other javascript code... 
var a = [1,2,3,4,5]; 
for (x in a){ 
    // Now foo is a part of EVERY array and 
    // will show up here as a value of 'x' 
} 

Было бы лучше для вас, чтобы создать свой собственный тип объекта конструктора в комплекте с функцией DoSomething, а не расширение встроенного массива.

+6

Я считаю, что конструкция "for (x in y)" предназначена для итерации над элементами объекта. Для индексированной итерации массива я не думаю, что это подходит. Тем не менее, ваша точка зрения на вмешательство в другой код на странице действительна - особенно если сторонние библиотеки используют in-in таким образом. – harto

+5

Да, инверсия верна - вам следует избегать ... в случае, если какой-то n00b модифицировал прототип Array, и вам следует избегать модификации прототипа Array в случае, если какой-то n00b использовался для ... в массиве. ;) – thomasrutter

+32

_right_ ответ в эти дни - использовать 'Object.defineProperty (Array.prototype, 'method', ...)', который сделает новый метод _non-enumerable_. – Alnitak

1

В общем, беспорядок с основными объектами javascript - плохая идея. Вы никогда не знаете, что могут ожидать некоторые сторонние библиотеки, и изменение основных объектов в javascript изменяет их для всего.

Если вы используете Prototype, это особенно плохо, потому что прототип беспорядок с глобальной областью также, и трудно сказать, собираетесь ли вы столкнуться или нет. Фактически изменение основных частей любого языка обычно является плохим даже в javascript.

(шепелявость может быть небольшим исключением там)

1

Вы дополненного общего типа, так сказать. Вероятно, вы перезаписали некоторые другие функции lib, и поэтому они перестали работать.

Предположим, что некоторый lib, который вы используете, расширяет массив с помощью функции Array.remove(). После загрузки библиотеки вы также добавите remove() в прототип Array, но со своей собственной функциональностью. Когда lib вызовет вашу функцию, он, вероятно, будет работать по-другому, как ожидалось, и нарушить его выполнение ... Вот что происходит здесь.

8

Следует проявлять осторожность! Может быть, вы сделали это: fiddle demo

Допустит, массив и метод Foo, который возвращает первый элемент:

var myArray = ["apple","ball","cat"]; 

foo(myArray) // <- 'apple' 

function foo(array){ 
    return array[0] 
} 

выше в порядке, потому что функции подняты к верху во время интерпретации.

Но это не работает: (Потому что прототип не definned)

myArray.foo() // <- 'undefined function foo' 

Array.prototype.foo = function(){ 
    return this[0] 
} 

Для этой работы, просто определить прототипы на вершине:

Array.prototype.foo = function(){ 
    return this[0] 
} 

myArray.foo() // <- 'apple' 

И ДА! Вы можете переопределить прототипы !!! Это ДОПУСКАЕТСЯ. Вы даже можете определить свой собственный метод add для массивов.

25

Хотя потенциал для сталкиваясь с другими битами O кодом»Переопределить функцию на прототипе еще риск, если вы хотите сделать это с современными версиями JavaScript, вы можете использовать метод Object.defineProperty, выключение перечислимого бита, например

// functional sort 
Object.defineProperty(Array.prototype, 'sortf', { 
    enumerable: false, 
    value: function(compare) { return [].concat(this).sort(compare); } 
}); 
+1

Не нужно указывать 'enumerable: false', поскольку' false' является значением по умолчанию 'enumerable'. – Noitidart

Смежные вопросы