Делегированная доходность (yield star, yield *) в функциях генератора
ECMAScript 6 должен содержать функции генератора и итераторы. Функция генератора (которая имеет function*
синтаксис) возвращает итератор. Итератор имеет next
метод, который при многократном вызове выполняет тело функции генератора, многократно останавливая и возобновляя выполнение на каждом yield
оператор.
Вики ECMAScript 6 по генераторам также представляет "делегированный доход" yield*
Оператор следующим образом:
yield*
оператор делегирует другому генератору. Это обеспечивает удобный механизм для создания генераторов.
Что означает "делегировать другому генератору"? Как я могу использовать yield*
"удобно составлять генераторы"?
[Вы можете играть с генераторами в Node v0.11.3 с помощью --harmony-generators
флаг.]
3 ответа
Делегирование другому генератору означает, что генератор тока прекращает производить значения сам по себе, вместо этого выдает значения, произведенные другим генератором, пока он не исчерпает его. Затем он возобновляет производство своих собственных значений, если таковые имеются.
Например, если secondGenerator()
производит числа из 10
в 15
, а также firstGenerator()
производит числа из 1
в 5
но делегаты secondGenerator()
после производства 2
то значения производятся firstGenerator()
будет:
1, 2, 10, 11, 12, 13, 14, 15, 3, 4, 5
function* firstGenerator() {
yield 1;
yield 2;
// Delegate to second generator
yield* secondGenerator();
yield 3;
yield 4;
yield 5;
}
function* secondGenerator() {
yield 10;
yield 11;
yield 12;
yield 13;
yield 14;
yield 15;
}
console.log(Array.from(firstGenerator()));
Делегированный yield не должен делегироваться только другому генератору, но любому итератору, поэтому первый ответ немного неубедителен. Рассмотрим этот простой пример:
`
function *someGenerator() {
yield 0;
yield [1,2,3]
yield* [1,2,3]
}
for (v of someGenerator()) {
console.log(v);
}
`
В самом генераторе нет другой функции - пока yield
делегаты итератору Array Object Iterator
;-)
function *gimme1to2_10to15_3to5() {
var ten = gimme10to15();
yield 1; yield 2;
for (var i = 10; i <= 20; i++)
yield *ten;
yield 3; yield 4; yield 5;
}
function *gimme10to15() {
for (var i = 10; i <= 15; i++)
var x = yield i;
}
let gen = gimme1to2_10to15_3to5();
var ar = [];
for (var i = 0; i < 12; i++)
{
var r = gen.next();
ar [i] = r.value + (r.done ? "!" : "..");
}
console.log (ar.join (", "));
Результат
1.., 2.., 10.., 11.., 12.., 13.., 14.., 15.., 3.., 4.., 5.., undefined!
Заметки
Функция с yield * запрашивает 11 значений у внутреннего генератора, но получает только те 10,15, которые должны. Звонки с избыточной доходностью * не действуют.
Значение done внутреннего генератора не влияет на done, который возвращает его вызывающий объект.
Вывод показывает неопределенное! в конце, потому что цикл тестирования написан так, чтобы он выходил за пределы необходимого числа значений, чтобы показать генератору done = true
Этот вывод взят с испытательного полигона ES6, Babel, и приведенная выше семантика должна считаться предварительной по состоянию на 5 февраля 2016 года.