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