Кратко
СкопированоИнструкция for
выполняет цикл обхода перечисляемых свойств объекта включая перечисляемые свойства прототипов.
В каждой итерации цикла переменная цикла получает значение соответствующее имени перечисляемого свойства объекта. Порядок обхода свойств строго определён спецификацией ECMAScript.
Перечисляемые свойства – это свойства, которые разработчик добавляет объекту.
В цикл for
не попадут: встроенные свойства, например методы объекта унаследованные от Object.prototype, а также свойства имена которых имеют тип Symbol
Как пишется
СкопированоСхематично структура для создания цикла выглядит так:
for (переменная in объект) { // действия внутри цикла}
for (переменная in объект) { // действия внутри цикла }
Для цикла необходимо объявить название переменной и указать сам объект, свойства которого нужно обойти. В объявленной переменной будет храниться имя свойства во время итерации:
const cat = { name: 'Борис', color: 'red', age: 8}for (const key in cat) { console.log(`${key} – ${cat[key]}`)}// name – 'Борис',// color – 'red',// age – 8
const cat = { name: 'Борис', color: 'red', age: 8 } for (const key in cat) { console.log(`${key} – ${cat[key]}`) } // name – 'Борис', // color – 'red', // age – 8
Как понять
СкопированоЦикл for
— это хороший способ пройти по всем свойствам объекта, но стоит помнить несколько важных особенностей.
Что такое перечисляемые свойства
СкопированоПеречисляемые свойства объекта – это свойства, которые явно помечены такими. Сказать свойству, что оно перечисляемое, можно через специальный метод define
. Но для простоты все свойства, которые добавляются к объекту, являются перечисляемыми по умолчанию. Встроенные свойства не перечисляется. Например, метод index
у объекта String
или метод to
у любого объекта не участвуют в цикле for
.
Цикл for
будет перебирать не только собственные свойства объекта, но и перечисляемые свойства наследуемые от цепочки прототипов. Имена свойств в цикле не повторяются (свойства объекта имеют наивысший приоритет, а свойства ближайших прототипов имеют больший приоритет над свойствами прототипов, находящихся дальше от объекта в его цепочке прототипов). :
const grandParent = { a: 1, b: 2 }const parent = { b: 3, c: 4 }const object = { c: 5 }Object.setPrototypeOf(parent, grandParent)Object.setPrototypeOf(object, parent)for (const key in object) { console.log(key, object[key])}// c 5// b 3// a 1
const grandParent = { a: 1, b: 2 } const parent = { b: 3, c: 4 } const object = { c: 5 } Object.setPrototypeOf(parent, grandParent) Object.setPrototypeOf(object, parent) for (const key in object) { console.log(key, object[key]) } // c 5 // b 3 // a 1
Если несколько объектов в цепочке прототипов имеют свойство с одинаковым именем, будет учитываться только первое из них, и оно будет участвовать в цикле только в том случае, если оно перечисляемое. Если оно неперечисляемое, никакие другие свойства таким же именем дальше по цепочке прототипов не будут участвовать в цикле, даже если они являются перечислимыми.
Порядок перечисления свойств
СкопированоСпецификация ECMAScript определяет следующий порядок обхода перечисляемых свойств объекта при выполнении цикла for
:
- неотрицательные целочисленные ключи (те, которые могут быть индексами массива) в порядке возрастания значений.
- строковые ключи в порядке возрастания хронологии создания.
В том же порядке будут перебираться свойства прототипов объекта.
Демонстрация порядка обхода целочисленных свойств:
const booksById = { 341: { name: 'Harry Potter' }, 144: { name: 'Flowers for Algernon' }, 202: { name: 'Lord of the Rings' }}for (const key in booksById) { console.log(key)}// 144// 202// 341
const booksById = { 341: { name: 'Harry Potter' }, 144: { name: 'Flowers for Algernon' }, 202: { name: 'Lord of the Rings' } } for (const key in booksById) { console.log(key) } // 144 // 202 // 341
Демонстрация порядка обхода объекта имеющего строковые и символьные свойств:
const id = Symbol('id')const developer = { name: 'Ваня', language: 'JavaScript', [id]: '8888', company: 'Google'}developer.age = 33for (const key in developer) { console.log(key)}// name// language// company// age
const id = Symbol('id') const developer = { name: 'Ваня', language: 'JavaScript', [id]: '8888', company: 'Google' } developer.age = 33 for (const key in developer) { console.log(key) } // name // language // company // age
Изменение объекта во время выполнения цикла for...in
СкопированоПо-возможности следует избегать изменения объекта при выполнении цикла.
Спецификация ECMAScript определяет случаи во время выполнения итерации при которых алгоритм работы цикла может нарушаться:
- модификация цепочки прототипов.
- удаление свойства из объекта или из объектов в цепочке прототипов.
- добавление свойства объекту из цепочки прототипов.
- изменение атрибута
enumerable
у свойств объекта или в объектах из цепочки прототипов.
Подсказки
Скопировано💡 Для получения списка перечисляемых свойств только самого объекта можно использовать статический метод Object