Каковы преимущества и опасности добавления методов в Object.prototype в Javascript? - PullRequest
7 голосов
/ 30 сентября 2010

Я знаю, что это был спорный вопрос, пять лет назад, но мне интересно, если что-то изменилось на сегодняшний JavaScript. Существуют ли реальные примеры того, как большая современная библиотека несовместима с расширением Object.prototype?

Меня не интересует гипотетический "кто-то может написать плохой for in код итерации в библиотеке, которую вы хотите использовать, возможно, в будущем, и тогда вы можете получить странную ошибку"

1 Ответ

12 голосов
/ 30 сентября 2010

Существуют ли в реальном мире примеры того, как большая современная библиотека несовместима с расширением Object.prototype?

Да, я помню проблемы с jQuery, который является одной из менее навязчивых библиотек, например:

Другой случай, который я помню, это то, что кто-то добавил функцию load к объекту Object.prototype, и это вызвало проблемы с событием $().load:

// DON'T DO THIS ! :)
Object.prototype.load = function () {};

​$(window).load(function () {
  alert('load event'); // never fired
});​

Пример здесь .

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

В ECMAScript 5 теперь существует более безопасный способ, потому что теперь мы можем объявлять не перечисляемые свойства, например:

Object.defineProperty(Object.prototype, 'foo', { value: 'bar' });

В дескрипторе свойства - { value: 'bar' } - мы можем указать атрибуты свойства, в случае Значение свойства , как в приведенном выше примере, мы можем указать атрибут writable и общий configurable attribute (определяет, может ли свойство быть переконфигурировано, - изменение атрибута или удаление.

И у нас также есть атрибут enumerable, который определяет, будет ли свойство перечисляться оператором for-in.

Если мы не указываем атрибуты, по умолчанию они false, дескриптор будет выглядеть так:

{
  value: 'bar',
  writable: false,
  configurable: false,
  enumerable: false
}
...