for...in

Цикл for...in проходит через перечисляемые свойства объекта, в произовольном порядке. Он пройдёт по каждому отдельному элементу.

Синтаксис

for (variable in object) {...
}
variable
Другое имя свойства назначается переменной на каждой итерации.
object
Объект, по чьим свойствам мы проходим

Описание

Цикл for...in проходит только по перечислимым свойствам. Объекты, созданные встроенными конструкторами, такими как Array и Object имеют неперечислимые свойства от Object.prototype и String.prototype, например, от String-это indexOf(), а от Object - метод toString(). Цикл пройдёт по всем перечислимым свойствам объекта, а также тем, что он унаследует от конструктора прототипа (свойства объекта в цепи прототипа).

Удаление, добавление и модификация свойств

Цикл for...in проходит по свойствам в произвольном порядке (см. оператор delete для того, чтобы узнать почему порядок прохода может отличаться в зависимости от браузера). Если свойство изменяется за одну итерацию, а затем изменяется снова, его значением в цикле является его последнее значение. Свойство, удаленное до того, как до него дошёл цикл, не будет участвовать в нём. Свойства добавленные в объекты в цикле могут быть пропущены. В общем, лучше не добавлять, изменять или удалять свойство из объекта во время итерации, если по нему ещё не прошли. Нет гарантии, что добавленное свойство будет посещено циклом, изменное после проведения изменений, а удалённое после удаления.

Проход по массиву и for...in

Замечание: for...in не следует использовать для Array, где важен порядок индексов.

Индексы массива перечисляемые свойства с целочисленными именами, а в остальном аналогичны объектам. Нет гарантии, что for...in будет возвращать индексы в нужном порядке и вернёт все перичисляемые свойства, включая имеющие нецелочислиненные имена и наследуемые.

Поэтому порядок прохода зависит от реализации, проход по массиву может не произойти в правильном порядке. Следовательно лучше с числовыми индексами использовать циклы forArray.prototype.forEach() или for...of, когда проходим по массивам, где важен порядок доступа к свойствам.

Проход только через собственные свойства.

Если вы хотите рассматривать только свойства самого объекта, а не его прототипов, используйте getOwnPropertyNames(), hasOwnProperty() или propertyIsEnumerable. Кроме того, если вы знаете, что не будет вмешательства в код извне, вы можете расширить встроенные прототипы методом проверки.

Примеры

Следующее выражение берёт аргументом объект. Затем проходит по всем перечислимым свойтвам объекта и возвращает строку содержащую имена свойств и их значения.

var obj = {a:1, b:2, c:3};
    
for (var prop in obj) {
  console.log("obj." + prop + " = " + obj[prop]);
}

// Выведет:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"

Следующая функция иллюстрирует использование hasOwnProperty(): наследуемые свойства не отображаются

var triangle = {a:1, b:2, c:3};

function ColoredTriangle() {
  this.color = "red";
}

ColoredTriangle.prototype = triangle;

var obj = new ColoredTriangle();

for (var prop in obj) {
  if( obj.hasOwnProperty( prop ) ) {
    console.log("obj." + prop + " = " + obj[prop]);
  } 
}

// Выведет:
// "obj.color = red"

Спецификации

Спецификация Статус Комментарий
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'for...in statement' в этой спецификации.
Стандарт  
ECMAScript 5.1 (ECMA-262)
Определение 'for...in statement' в этой спецификации.
Стандарт  
ECMAScript 3rd Edition (ECMA-262)
Определение 'for...in statement' в этой спецификации.
Стандарт  
ECMAScript 1st Edition (ECMA-262)
Определение 'for...in statement' в этой спецификации.
Стандарт Изначальное определение

Поддержка браузерами

Возможность Chrome Firefox (Gecko) Internet Explorer Opera Safari
Базовая поддержка (Да) (Да) (Да) (Да) (Да)
Возможность Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Базовая поддержка (Да) (Да) (Да) (Да) (Да) (Да)

Поддержка: инициализатор переменных

До SpiderMonkey 40 (Firefox 40 / Thunderbird 40 / SeaMonkey 2.37), можно было инициализировать переменные (i=0) в цикле for...in:

var obj = {a:1, b:2, c:3};
for(var i=0 in obj) {
  console.log(obj[i]);
}
// 1
// 2
// 3

Это нестандартное поведение игнорируется в версии 40 и более поздних, оно бросит предупреждение SyntaxError ("for-in loop head declarations may not have initializers") в консоль (ошибка 748550 и ошибка 1164741).

Другие движки, такие как v8 (Chrome), Chakra (IE/Edge) и JSC (WebKit/Safari) также собираются удалить это нестандартное поведение.

Смотрите также

Метки документа и участники

 Внесли вклад в эту страницу: BychekRU
 Обновлялась последний раз: BychekRU,