# Объекты: перебор свойств Для перебора всех свойств из объекта используется цикл по свойствам `for..in`. Эта синтаксическая конструкция отличается от рассмотренного ранее цикла `for(;;)`. [cut] ## for..in [#for..in] Синтаксис: ```js for (key in obj) { /* ... делать что-то с obj[key] ... */ } ``` При этом `for..in` последовательно переберёт свойства объекта `obj`, имя каждого свойства будет записано в `key` и вызвано тело цикла. [smart header="Объявление переменной в цикле `for (var key in obj)`"] Вспомогательную переменную `key` можно объявить прямо в цикле: ```js for (*!*var key*/!* in menu) { // ... } ``` Так иногда пишут для краткости кода. Можно использовать и любое другое название, кроме `key`, например `for(var propName in menu)`. [/smart] Пример итерации по свойствам: ```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 во всех браузерах } ``` ## Итого