Перейти к содержанию

Цикл 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. Пишите код, который будет в наименьшей мере зависеть от окружения, в котором он будет запущен — не стоит гадать, расширял кто-то прототипы или нет и используется ли в ней та или иная библиотека.