Как и оператор in, цикл for in проходит по всей цепочке прототипов обходя свойства объекта.
Примечание: Цикл
for inне обходит те свойства объекта, у которых атрибутenumerableустановлен вfalse; как пример - свойствоlengthу массивов
// Испортим Object.prototype
Object.prototype.bar = 1;
var foo = {moo: 2};
for(var i in foo) {
console.log(i); // печатает и bar и moo
}
Так как изменить поведение цикла for in как такового не представляется возможным, то для фильтрации нежелательных свойств объекта внутри этого цикла используют метод hasOwnProperty из Object.prototype.
Примечание: Цикл
for inвсегда обходит всю цепочку прототипов полностью: таким образом, чем больше прототипов (слоёв наследования) в цепочке, тем медленнее работает цикл.
// возьмём foo из примера выше
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}
Это единственная версия правильного использования цикла. Благодаря использованию hasOwnPropery будет выведено только свойство moo. Если же убрать hasOwnProperty, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как Object.prototype.
Один из самых популярных фреймворков Prototype как раз этим и славится, и если вы его подключаете, то не забудьте использовать hasOwnProperty внутри цикла for in, иначе у вас гарантированно возникнут проблемы.
Рекомендация одна — всегда используйте hasOwnProperty. Пишите код, который будет в наименьшей мере зависеть от окружения, в котором он будет запущен — не стоит гадать, расширял кто-то прототипы или нет и используется ли в ней та или иная библиотека.