В чём разница между этими фрагментами кода?
yield *smth;
for (let x of smth) {
yield x;
}
@torazaburo в комментарии сказал
This is an OK simplification, but it fails to address what the yield *generator() evaluates to, which as it turns out is the end-of-iteration value return'ed by the generator object. It also does not correctly represent what happens when the consumer of the generator throws into the generator, etc.
Хотелось бы узнать, в чём именно заключается разница и в каких случаях она проявит себя.
Ответ
На самом деле, синтаксис yield * gen используется для передачи управления внутрь другого генератора.
Вот что об этом говорит MDN
The yield* expression iterates over the operand and yields each value returned by it.
А вот и пример того, как это работает:
let seqPos = function * (max) {
for (let i = 1; i <= max; i++) {
yield i;
}
}
let seqNeg = function * (min) {
let start = min > 0 ? -1*min : min;
for (let i = start; i < 0; i++) {
yield i;
}
}
let seq = function * (val) {
yield * seqNeg(-1*val);
yield 0;
yield * seqPos(val);
}
for (let i of seq(2)) {
console.log(i);
}
Пример выше выведет:
-2
-1
0
1
2
А вот и JSFiddle с примером.
Что касается основного вопроса, то разница между конструкциями:
for (let val of gen) {
yield val;
}
и
yield * gen;
заключается в том, что в первом случае всего лишь возвращаются значения дочернего генератора, а во втором управление полностью передается дочернему генератору.
Это значит, что вызов методов Generator.prototype.next, Generator.prototype.throw и Generator.prototype.return клиентским кодом на родительском генераторе будет адресован дочернему генератору:
let innerGen = function * () {
try {
for (let i = 0; i < 3; i++) {
console.log(yield i);
}
} catch (e) {
console.log('Got you!');
}
}
let outerGen = function * () {
let child = innerGen();
yield * child;
}
let g = outerGen();
g.next();
g.next("foo"); // выведет в консоль "foo"
g.throw(new Error('Oops!')); // выведет "Got you!"
Ситуация, с пробросом исключений в дочерний итератор, описанная участником @Роман Парадеев в соседнем ответе, является всего лишь частным случаем передачи управления дочернему генератору.
Комментариев нет:
Отправить комментарий