en.javascript.info/1-js/4-data-structures/5-object-for-in/article.md
Ilya Kantor 05a93ced80 edit
2016-03-04 19:06:22 +03:00

7.3 KiB
Raw Blame History

Объекты: перебор свойств

Для перебора всех свойств из объекта используется цикл по свойствам for..in. Эта синтаксическая конструкция отличается от рассмотренного ранее цикла for(;;).

[cut]

for..in [#for..in]

Синтаксис:

for (key in obj) {
  /* ... делать что-то с obj[key] ... */
}

При этом for..in последовательно переберёт свойства объекта obj, имя каждого свойства будет записано в key и вызвано тело цикла.

````smart header="Объявление переменной в цикле for (var key in obj)" Вспомогательную переменную key можно объявить прямо в цикле:

for (*!*var key*/!* in menu) {
  // ...
}

Так иногда пишут для краткости кода. Можно использовать и любое другое название, кроме key, например for(var propName in menu).


Пример итерации по свойствам:

```js run
var menu = {
  width: 300,
  height: 200,
  title: "Menu"
};

for (var key in menu) {
  // этот код будет вызван для каждого свойства объекта
  // ..и выведет имя свойства и его значение

*!*
  alert( "Ключ: " + key + " значение:" + menu[key] );
*/!*
}
```

Обратите внимание, мы использовали квадратные скобки `menu[key]`. Как уже говорилось, если имя свойства хранится в переменной, то обратиться к нему можно только так, не через точку.

## Количество свойств в объекте

Как узнать, сколько свойств хранит объект?

Готового метода для этого нет.

Самый кросс-браузерный способ -- это сделать цикл по свойствам и посчитать, вот так:

```js run
var menu = {
  width: 300,
  height: 200,
  title: "Menu"
};

*!*
var counter = 0;

for (var key in menu) {
  counter++;
}
*/!*

alert( "Всего свойств: " + counter );
```

В следующих главах мы пройдём массивы и познакомимся с другим, более коротким, вызовом: `Object.keys(menu).length`.

## В каком порядке перебираются свойства?

Для примера, рассмотрим объект, который задаёт список опций для выбора страны:

```js
var codes = {
  // телефонные коды в формате "код страны": "название"
  "7": "Россия",
  "38": "Украина",
  // ..,
  "1": "США"
};
```

Здесь мы предполагаем, что большинство посетителей из России, и поэтому начинаем с `7`, это зависит от проекта.

При выборе телефонного кода мы хотели бы предлагать варианты, начиная с первого. Обычно на основе списка генерируется `select`, но здесь нам важно не это, а важно другое.

**Правда ли, что при переборе `for(key in codes)` ключи `key` будут перечислены именно в том порядке, в котором заданы?**

**По стандарту -- нет. Но некоторое соглашение об этом, всё же, есть.**

Соглашение говорит, что если имя свойства -- нечисловая строка, то такие ключи всегда перебираются в том же порядке. Так получилось по историческим причинам и изменить это сложно: поломается много готового кода.

С другой стороны, если имя свойства -- число, то все современные браузеры сортируют такие свойства в целях внутренней оптимизации.

К примеру, рассмотрим объект с заведомо нечисловыми свойствами:

```js run
var user = {
  name: "Вася",
  surname: "Петров"
};
user.age = 25;

*!*
// порядок перебора соответствует порядку присвоения свойства
*/!*
for (var prop in user) {
  alert( prop ); // name, surname, age
}
```

А теперь -- что будет, если перебрать объект с кодами?

```js run
var codes = {
  // телефонные коды в формате "код страны": "название"
  "7": "Россия",
  "38": "Украина",
  "1": "США"
};

for (var code in codes) alert( code ); // 1, 7, 38
```

При запуске этого кода в современном браузере мы увидим, что на первое место попал код США!

Нарушение порядка возникло, потому что ключи численные. Интерпретатор JavaScript видит, что строка на самом деле является числом и преобразует ключ в немного другой внутренний формат. Дополнительным эффектом внутренних оптимизаций является сортировка.

**А что, если мы хотим, чтобы порядок был именно таким, какой мы задали?**

Это возможно. Можно применить небольшой хак, который заключается в том, чтобы сделать все ключи нечисловыми, например, добавим в начало дополнительный символ `'+'`:

```js run
var codes = {
  "+7": "Россия",
  "+38": "Украина",
  "+1": "США"
};

for (var code in codes) {
  var value = codes[code];
  code = +code; // ..если нам нужно именно число, преобразуем: "+7" -> 7

  alert( code + ": " + value ); // 7, 38, 1 во всех браузерах
}
```

## Итого

- Цикл по ключам: `for (key in obj)`.
- Порядок перебора соответствует порядку объявления для нечисловых ключей, а числовые -- сортируются (в современных браузерах).
- Если нужно, чтобы порядок перебора числовых ключей соответствовал их объявлению в объекте, то используют трюк: числовые ключи заменяют на похожие, но содержащие не только цифры. Например, добавляют в начало `+`, как описано в примере выше, а потом, в процессе обработки, преобразуют такие ключи в числа.