добавление пользовательских функций в массив.прототип

Я работал над AJAX-поддержкой asp.net применение. Я только что добавил некоторые методы в Array.прототип как

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

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

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

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

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

5 ответов


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

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

чтобы проиллюстрировать, используя пример (заимствованный из здесь):

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, а не расширять встроенный массив.


Edit: чтобы повторить то, что я поставил в комментарии:

обратное верно-вы должны избегать for..in в случае, если некоторый n00b изменил прототип массива, и вы должны избегать изменения прототипа массива в случае, если некоторый n00b использовал for..in на массиве. ;)

кроме того, сейчас существует Object.defineProperty как общий способ расширения прототипов объектов без перечисления новых свойств, хотя я все равно не буду использовать это в качестве оправдания для расширения встроенный типы, потому что даже помимо for..in есть еще потенциал для других конфликтов с другими скриптами. Подумайте о том, что кто-то разветвляет ваш код, а затем помещает обе версии на одну страницу - будет ли ваше пользовательское улучшение объекта Array работать, как вы ожидаете?


в то время как потенциал для столкновения с другими битами кода переопределение функции на прототипе по-прежнему является риском, если вы хотите сделать это с современными версиями JavaScript, вы можете использовать объект.метод defineProperty, отключая перечисляемый бит, например

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

есть осторожно! Может быть, вы сделали это:скрипка демо

скажем, массив и метод foo, которые возвращают первый элемент:

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

foo(myArray) // <- 'apple'

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

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

но это не работает: (потому что прототип не определен)

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

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

чтобы это работало, просто определите прототипы вверху:

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

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

и да! Вы можете переопределить прототипы!!! Это разрешено. Вы даже можете определить свой собственный add метод для массивов.


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

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

(lisp может быть, небольшое исключение)


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

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