for...in
Інструкція for...in
("для кожного ... у") ітерує всі перелічувані рядкові властивості об'єкта (ігноруючи ті, ключами яких є символи), в тому числі успадковані перелічувані властивості.
Спробуйте його в дії
Синтаксис
for (variable in object)
statement
Параметри
variable
На кожній ітерації отримує ім'я рядкової властивості. Може бути або оголошенням з
const
,let
чиvar
, або ціллю присвоєння (наприклад, заздалегідь оголошеною змінною чи властивістю об'єкта).object
Об'єкт, чиї перелічувані властивості з несимвольними ключами перебираються.
statement
Інструкція, що виконається на кожній ітерації. Може звертатися до
variable
. Для виконання декількох інструкцій можна використати блокову інструкцію.
Опис
Цикл опрацює всі власні перелічувані властивості об'єкта, а також ті, що успадковуються об'єктом від його прототипного ланцюжка (властивості ближчих прототипів мають перевагу над властивостями тих прототипів, які знаходяться далі від об'єкта у ланцюжку прототипів).
Цикл for...in
перебирає лише перелічувані несимвольні властивості. Об'єкти, які створюються за допомогою таких вбудованих конструкторів, як Array
і Object
, мають неперелічувані властивості, успадковані від Array.prototype
та Object.prototype
, як от метод indexOf()
об'єкта Array
чи метод toString()
об'єкта Object
. Такі властивості не оброблятимуться циклом for...in
.
Порядок перебирання властивостей, згідно зі сучасною специфікацією ECMAScript — чітко визначений, і незмінний між реалізаціями. Всередині кожного компонента прототипного ланцюжка всі ключі, які є додатними цілими числами (зазвичай це індекси масивів) опрацьовуються першими, в порядку зростання числового значення. Потім опрацьовуються інші рядкові ключі, в хронологічному порядку відносно дати створення кожної властивості.
Частина for...in
variable
приймає що завгодно, що може стояти зліва оператора =
. Якщо не робити присвоєння змінній всередині тіла циклу, то можна для її оголошення використати const
(таке присвоєння не вплине на наступну ітерацію, адже в ній буде геть окрема змінна). Інакше – можна використати let
. Також можна застосувати деструктурування чи властивість об'єкта, як то for (x.y in iterable)
.
Застарілий синтаксис дозволяє оголошенням var
змінної циклу мати ініціалізатор. Це викидає синтаксичну помилку в строгому режимі й ігнорується в нестрогому.
Видалені, додані чи змінені властивості
Якщо під час однієї з ітерацій властивість змінюється, а потім опрацьовується в одній з наступних ітерацій, в циклі буде використано те значення, яке вона має на момент її опрацювання другого разу. Властивість, яку було видалено перед своєю обробкою, пізніше оброблено не буде. Властивості, які додаються до об'єкта під час перебирання його властивостей, можуть бути як оброблені пізніше, так і пропущені в циклі.
Загалом, під час ітерування краще не додавати, не змінювати й не видаляти властивості з об'єкта, окрім властивості, котра безпосередньо обробляється поточною ітерацією. Немає ніяких гарантій того, що додана властивість буде опрацьована циклом, чи буде змінена властивість оброблена до, чи після модифікації, і чи буде видалена властивість опрацьована до моменту видалення.
Ітерування масиву і цикл for...in
Індекси масиву — це лише перелічувані властивості, які у всьому ідентичні властивостям звичайних об'єктів, окрім того, що їхні імена — це цілі числа. Цикл for...in
обробить всі ключі, які є цілими числами, перед початком обробки інших ключів, чітко у напрямку їхнього зростання, що робить поведінку інструкції for...in
близькою до звичайного перебирання масиву. Проте, цикл for...in
також поверне всі перелічувані властивості, включно з успадкованими й тими, чиї ключі не є цілими числами. На відміну від for...of
, for...in
використовує перелічування властивостей замість ітератора масиву. У розріджених масивах for...of
буде обробляти порожні гнізда, а for...in
— ні.
Краще використовувати цикл for
з числовим індексом, Array.prototype.forEach()
чи цикл for...of
, оскільки вони повертатимуть індекс як число, а не як рядок, а також уникатимуть властивостей поза індексом.
Перебирання лише власних властивостей об'єкта
В разі, якщо необхідно розглянути лише ті властивості, які приєднані до самого об'єкта, без урахування його прототипів, можна застосувати один із наступних підходів:
Object.keys
поверне список власних перелічуваних властивостей із рядковими ключами, а от Object.getOwnPropertyNames
також міститиме неперелічувані властивості.
Багато настанов щодо стилю та лінтерів у JavaScript рекомендують не застосовувати for...in
через те, що він перебирає весь ланцюжок прототипів, а це рідко є бажаним. Також його часто плутають із більш вживаним циклом for...of
. Найбільш доцільним може бути його використання для потреб зневадження, як простого способу перевірити властивості об'єкта (шляхом виведення їх у консоль, або ж інакшим чином). В ситуаціях, коли об'єкти використовуються як утилітарні пари ключ-значення, for...in
дає змогу перевірити, чи зберігає якийсь з таких ключів певне значення.
Приклади
Застосування for...in
Цикл for...in
, який наведено нижче, перевіряє всі перелічувані, несимвольні властивості об'єкта, і для кожної друкує рядок з іменем властивості та її значенням.
const obj = { a: 1, b: 2, c: 3 };
for (const prop in obj) {
console.log(`obj.${prop} = ${obj[prop]}`);
}
// Друкує:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
Перебирання власних властивостей об'єкта
Наступна функція демонструє використання методу Object.hasOwn()
: успадковані властивості не виводяться.
const triangle = { a: 1, b: 2, c: 3 };
function ColoredTriangle() {
this.color = "red";
}
ColoredTriangle.prototype = triangle;
var obj = new ColoredTriangle();
for (const prop in obj) {
if (Object.hasOwn(obj, prop)) {
console.log(`obj.${prop} = ${obj[prop]}`);
}
}
// Друкує:
// "obj.color = red"
Специфікації
Сумісність із браузерами
desktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
for...in
|
Chrome Full support 1 | Edge Full support 12 | Firefox Full support 1 | Internet Explorer Full support 3 | Opera Full support 2 | Safari Full support 1 | WebView Android Full support 4.4 | Chrome Android Full support 18 | Firefox for Android Full support 4 | Opera Android Full support 10.1 | Safari on iOS Full support 1 | Samsung Internet Full support 1.0 | Deno Full support 1.0 | Node.js Full support 0.10.0 |