return val++; // Иначе вернуть следующее число
} // и увеличить позицию
};
}
};
}
// Далее демонстрируется, как можно выполнять итерации по диапазону:
for(let і in range(1,10)) console.log(i); // Выведет числа от 1 до 10
Обратите внимание, что, несмотря на необходимость писать метод __iterator__()
и возбуждать исключение Stoplteration
для создания итерируемых объектов и их итераторов, вам не придется (в обычной ситуации) вызывать метод __iterator__()
и/или обрабатывать исключение Stoplteration
- все это сделает цикл for/in
. Если по каким-то причинам потребуется явно получить объект-итератор итерируемого объекта, можно воспользоваться функцией Iterator()
. ( Iterator()
- это глобальная функция, которая появилась в версии JavaScript 1.7.) Если передать этой функции итерируемый объект, она просто вернет результат вызова метода __iterator__()
, что придаст дополнительную ясность программному коду. (Если передать функции Iterator()
второй аргумент, она передаст его методу __iterator__()
.)
Однако функция Iterator()
имеет еще одно важное назначение. Если ей передать объект (или массив), не имеющий метода __iterator__()
, она вернет собственную реализацию итерируемого итератора для объекта. Каждый вызов метода next()
этого итератора будет возвращать массив с двумя значениями. В первом элементе массива будет возвращаться имя свойства объекта, а во втором - значение этого свойства. Поскольку этот объект является итерируемым итератором, его можно использовать в цикле for/in
вместо прямого вызова метода next(),
а это означает, что функцию Iterator()
можно использовать совместно с операцией присваивания с разложением при выполнении итераций по свойствам и значениям объекта или массива:
for(let [k,v] in Iterator({a:1,b:2})) // Итерации по ключам и значениям
console.log(k + "=" + v); // Выведет "a=1" и "b=2"
Итератор, возвращаемый функцией Iterator(),
имеет еще две важные особенности. Во-первых, он игнорирует унаследованные свойства и выполняет итерации только по «собственным» свойствам, что чаще всего и требуется. Во-вторых, если передать функции Iterator()
значение true
во втором аргументе, возвращаемый итератор будет выполнять итерации только по именам свойств, без их значений. Обе эти особенности демонстрируются в следующем примере:
о={х:1,у:2} // Объект с двумя свойствами
Object.prototype.z = 3; // Теперь все объекты унаследуют z
for(p in о) console.log(p); // Выведет "x", "у" и ”z"
for(р in Iterator(o, true)) console.log(p); // Выведет только “x" и "у"
Генераторы - это особенность JavaScript 1.7 (заимствованная из языка Python), основанная на использовании нового ключевого слова yield
. Программный код, использующий данную особенность, должен явно указать номер версии 1.7, как описывалось в разделе 11.2. Ключевое слово yield
используется в функциях и действует аналогично инструкции return
, возвращая значение из функции. Разница между yield
и return
состоит в том, что функция, возвращающая значение с помощью ключевого слова yield
, сохраняет информацию о своем состоянии, благодаря чему ее выполнение может быть возобновлено. Такая способность к возобновлению выполнения делает yield
замечательным инструментом для создания итераторов. Генераторы - очень мощная особенность языка, но понять принцип их действия совсем не просто. Для начала познакомимся с некоторыми определениями.
Любая функция, использующая ключевое слово yield
(даже если инструкция yield
никогда не будет выполняться), является функцией-генератором. Функции-генераторы возвращают значения с помощью yield
. Они могут использовать инструкцию return
без значения, чтобы завершиться до того, как будет достигнут конец тела функции, но они не могут использовать return
со значением. За исключением использования ключевого слова yield
и ограничений на использование инструкции return
, функции-генераторы ничем не отличаются от обычных функций: они объявляются с помощью ключевого слова function
, оператор typeof
возвращает для них строку «function» и как обычные функции они наследуют свойства и методы от Function.prototype
. Однако поведение функции-генератора совершенно отличается от поведения обычной функции: при вызове, вместо того чтобы выполнить свое тело, функция-генератор возвращает объект генератора.
Читать дальше
Конец ознакомительного отрывка
Купить книгу