Вот уже в который раз наблюдаю использование в коде сторонней библиотеки попытки сделать всё красиво за счёт добавления функций в Object.prototype.
Object.prototype.Foo = function()
{
// Что-то делаем здесь.
}
На первый взгляд может показаться, что нет ничего страшного в таком коде. Но, стоит только вспомнить один из самых распространённых вариантов использования объектов в JavaScript: “Object as hash-tables” и:
var myHashTable = { "key1" : "value1", "key2" : "value2" };
for (var key in myHashTable)
{
// используется функция логирования от расширения Firebug (http://getfirebug.org/).
console.log("key = '" + key + "', value = '" + myHashTable[key] + "';");
}
// Вывод:
// key = 'key1', value = 'value1';
// key = 'key2', value = 'value2';
// key = 'Foo', value = 'function () { }'; // WTF???
Упс. В импровизированной хэш-табличке, внезапно, появился новый забавный элемент.
Неприятно обнаруживать, что ошибки в твоём коде обусловлены использованием чужой библиотекой. Да и избавиться от такого бага довольно непросто: он заставляет либо отказаться от использования “Объект как хэш-таблица” (подменив на свою реализацию), либо от использования сторонней библиотеки (в некоторых случаях гораздо проще).
Чтобы обнаружить этот баг на ранней стадии, имеет смысл добавить в свои unit-тесты следующий тест:
testObjectAsHashTableAreEmptyByDefault = function()
{
var obj = {};
var keysCount = 0;
for (var key in obj) { keysCount++; }
assertEquals(keysCount, 0);
}
Разработчикам же, библиотек для JavaScript нелишне будет запомнить, что Object.prototype – это тайна за семью печатями (sealed).
thanks
ОтветитьУдалитьДобрый вечер.
ОтветитьУдалитьПростите за глупый вопрос, но Object.prototype подразумевается любой объект, правильно?
И тогда вопрос отсюда вытекающий - как тогда правильно расширить свойства объекта?
Ваши бы слова да разработчикам в уши. Вот приходит ко мне пользователь моей библиотеки и просит сделать обход свойств объекта у меня, чтобы я не натыкался на его прототипированную функцию - вот где веселье.
ОтветитьУдалитьА вы пользователю скажите, чтобы он, влезая в прототип использовал
ОтветитьУдалитьObject.defineProperty(Array.prototype, "имя_свойства", {enumerable: false})
Или сами у себя проверяйте hasOwnProperty