Цикл 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' в этой спецификации.
Стандарт Изначальное определение

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

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

Возможность 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) также собираются удалить это нестандартное поведение.

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

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

Внесли вклад в эту страницу: olvin-hh, AliaksandrZahorski, Jarith, UriShlomov, a1ia5, BychekRU
Обновлялась последний раз: olvin-hh,