ES6 - итераторы

Поговорим о ECMAScript 2015

Предыдущий



итератор и итерируемый

Итератор - это объект с методом next, который возвращает кортежи {done, value}.

ES6 дает нам шаблон для создания настраиваемых итераторов, и его реализация аналогична Java Iterable или .NET IEnumerable. Он также имеет встроенные итерации: String, Array, TypedArray, Map. и Установить. Объектом итератора может быть любой объект с методом next ().

Iterable - это объект, внутри которого есть метод [Symbol.iterator] ().

Символ, в свою очередь, представляет собой уникальный и неизменяемый тип данных, который можно использовать в качестве идентификатора для свойств объекта - эквивалента в ES5 нет.

// Symbol
let s1 = Symbol('abc');
let s2 = Symbol('abc');
console.log(s1 !== s2); // true
console.log(typeof s1); // 'symbol'
let obj = {};
obj[s1] = 'abc';
console.log(obj); // Object { Symbol(abc): 'abc' }

Давайте посмотрим на простой итератор, написанный с нуля, который позволяет нам перебирать случайные числа, динамически генерируемые методом next (). Функция, возвращающая повторяющийся объект, принимает один аргумент (items), который используется для определения, должен ли итератор останавливаться, и возвращает done = true.

let random1_10 = function (items = 1) {
  return {
    [Symbol.iterator]() {
      let cur = 0;
      return {
        next() {
          let done = cur === items,
              random = Math.floor(Math.random() * 10) + 1;
          ++cur;
          return {
            done: done,
            value: random
          }
        }
      }
    }
  };
};
for (let n of random1_10(5)) {
  console.log(n); // prints 5 random numbers
}

Каждый раз, когда цикл for-of вызывает метод next (), итератор генерирует случайное число и возвращает его в цикл.

Если итератор возвращает done = true, вы можете опустить значение, поэтому результатом будет
{done: true}.

let random1_10 = function (items = 1) {
  return {
    [Symbol.iterator]() {
      let cur = 0;
      return {
        next() {
          if (cur === items) {
            return {
              done: true 
            }
          }
          ++cur;
          return {
            done: false,
            value: Math.floor(Math.random() * 10) + 1
          }
        }
      }
    }
  };
};
for (let n of random1_10(5)) {
 console.log(n); // prints 5 random numbers
}

цикл for-of

В ES6 появился новый цикл - for-of. Он работает с итерациями. Посмотрим на его подпись:

for (LET of ITERABLE) {
  CODE BLOCK
}

Он похож на цикл for-in, который можно использовать для перебора свойств объекта (простые старые объекты).

Массивы в ES6 по умолчанию итерируемы, поэтому мы, наконец, можем использовать for-of для перебора элементов.

const arr = [1, 2, 3, 4, 5];
for (let item of arr) {
  console.log(item); // 1
                     // 2
                     // 3
                     // 4
                     // 5
}

Внутри цикла for-of мы можем даже использовать break, continue и return.

const arr = [1, 2, 3, 4, 5];
for (let item of arr) {
  if (item > 4) {
    break;
  }
  if (0 !== item % 2) {
    continue;
  }
  console.log(item); // 2
                     // 4
}

Следующий



Нравится? Рекомендую!



Вся серия также доступна в виде электронной книги. Я опубликовал это на Leanpub.com



Будущее светлое!