Цикл for in¶
Как и оператор 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
всегда обходит всю цепочку прототипов полностью: таким образом, чем больше прототипов (слоёв наследования) в цепочке, тем медленнее работает цикл.
Использование hasOwnProperty в качестве фильтра¶
// возьмём foo из примера выше
for (var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i)
}
}
Это единственная версия правильного использования цикла. Благодаря использованию hasOwnProperty
будет выведено только свойство moo
. Если же убрать hasOwnProperty
, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как Object.prototype
.
Один из самых популярных фреймворков Prototype как раз этим и славится, и если вы его подключаете, то не забудьте использовать hasOwnProperty
внутри цикла for in
, иначе у вас гарантированно возникнут проблемы.
Рекомендации¶
Рекомендация одна — всегда используйте hasOwnProperty
. Пишите код, который будет в наименьшей мере зависеть от окружения, в котором он будет запущен — не стоит гадать, расширял кто-то прототипы или нет и используется ли в ней та или иная библиотека.