ES6 в деталях: Итераторы и циклы for-of

May 21, 2015

ES6 в деталях — это цикл статей о новых возможностях языка
программирования JavaScript, появившихся в 6 редакции стандарта ECMAScript,
кратко — ES6.

Как перебрать все элементы массива?
Двадцать лет назад, когда JavaScript только появился, мы бы сделали так:

for (var index = 0; index < myArray.length; index++) {
console.log(myArray[index]);
}

Начиная с ES5, можно воспользоваться встроенным методом forEach:

myArray.forEach(function (value) {
console.log(value);
});

Так немного короче, но есть небольшой недостаток: нельзя прервать выполнение
цикла ключевым словом break или выйти из внешней функции через
return.

Разумеется, было бы хорошо, если бы синтаксис цикла for просто позволял
перебрать все элементы массива.

Как насчёт цикла for-in?

for (var index in myArray) {    // вообще-то, не стоит так делать
console.log(myArray[index]);
}

Это плохое решение, по нескольким причинам:

  • Значения, присваиваемые index в этом коде — строки "0", "1", "2"
    и т.д., а не настоящие числа. Вам, наверняка, не хотелось бы иметь дело
    со строковой арифметикой ("2" + 1 == "21"), и поэтому это, по меньшей
    мере, неудобно.

  • Тело цикла будет выполнено не только для элементов массива, но и для всех
    expando-свойств, кем-либо добавленных. К примеру, если в вашем массиве
    есть перечисляемое свойство myArray.name, то этот цикл выполнится один
    лишний раз, с index == "name". Цикл может пройтись даже по свойствам из
    цепочки прототипов массива.

  • Самое изумительное: при некоторых обстоятельствах этот код может обойти
    элементы массива в произвольном порядке.


Если кратко, for-in рассчитан на работу с обычными объектами Object
с именами свойств в виде строк. Для массивов он подходит не так хорошо.

Могущественный цикл for-of

Помните, на прошлой неделе я обещал, что ES6 не сломает тот код на JS, что вы
уже написали?
Вот, миллионы сайтов зависят от поведения for-in, да, даже от того, как он
работает с массивами.
Так что о том, чтобы «поправить» for-in и сделать его более полезным для
массивов, не было и речи. Единственный способ, которым ES6 может улучшить
ситуацию — добавить какой-нибудь новый синтаксис.

И вот так он выглядит:

for (var value of myArray) {
console.log(value);
}

Хмм… После моего интригующего описания вы, наверное, ожидали чего-то более
впечатляющего?
Что ж, давайте взглянем, есть ли у for-of козырь в рукаве.
Для начала отметим, что:

  • это самый лаконичный и наглядный синтаксис для перебора элементов массивов;
  • у него нет недостатков for-in;
  • в отличие от forEach(), он работает с break, continue и return.

Циклы for-in нужны для перебора свойств объекта.

Циклы for-of нужны для перебора данных, например, значений массива.

Но это ещё не всё.

Использование for-of с другими коллекциями

for-of не только для массивов. Он также работает с большинством
массивоподобных объектов, вроде списковNodeList в DOM.

Ещё он работает со строками, рассматривая строку как набор символов Unicode:

for (var chr of "

Комментарии

comments powered by Disqus