1 августа 2019 г.

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

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/object.

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

for..in

Синтаксис:

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

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

Объявление переменной в цикле for (var key in obj)

Вспомогательную переменную key можно объявить прямо в цикле:

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

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

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

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

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

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

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

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

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

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

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

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

var counter = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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).
  • Порядок перебора соответствует порядку объявления для нечисловых ключей, а числовые – сортируются (в современных браузерах).
  • Если нужно, чтобы порядок перебора числовых ключей соответствовал их объявлению в объекте, то используют трюк: числовые ключи заменяют на похожие, но содержащие не только цифры. Например, добавляют в начало +, как описано в примере выше, а потом, в процессе обработки, преобразуют такие ключи в числа.
Карта учебника

Комментарии

перед тем как писать…
  • Если вам кажется, что в статье что-то не так - вместо комментария напишите на GitHub.
  • Для одной строки кода используйте тег <code>, для нескольких строк кода — тег <pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)
  • Если что-то непонятно в статье — пишите, что именно и с какого места.