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