Первый it.next()
соответствует yield(x + 1)
, что приводит к 6, как и ожидалось. 12 в следующем вызове it.next(12)
устанавливает значение этого первого урона равным 12, поэтому значение y
удваивает это значение, или 24, и итератор приводит к значению (y/3)
, которое равно 8. Окончательный вызов it.next(13)
устанавливает значение второй выход 13, который установлен в z
, и принимает значение return
, что 5 + 24 + 13.
Конечно, это немного сбивает с толку, из-за синтаксиса
z = yield(y/3)
, который как-то выглядит как один, присваивает значение как-то связанному с y/3
с z
. Это не так. y/3
- значение, которое должно служить значением итератора, тогда как z
присваивается значению, переданному , следующемуit.next()
, что-то совершенно другое! Это может быть немного полезно опустить скобки и записать это как
var y = 2 * yield x + 1;
var z = yield y/3;
, имея в виду, что yield
это утверждение, а не вызов функции.
Что касается ошибки, которую вы упомянули, в трассировке, например, это «Отправлено значение новорожденному генератору». Это имеет смысл, когда вы об этом думаете. Значение, отправляемое как параметр в it.next()
, становится значением последних выход в генераторе. При первом вызове it.next()
там нет самого последнего выхода в генераторе, поэтому нет ничего, чтобы принять переданное значение, следовательно, ошибка.
Не следует путать передачи параметров генератора (x
в вашем случае), который просто обеспечивает способ настройки или инициализировать генератор с передачей параметрами it.next()
, которые служат в качестве значения самого последнего yield
в генератор.
Это может быть полезно рассмотреть, как можно было бы написать эквивалентную скрученные вручную генератор (упрощенный просто возвращает следующее значение вместо {value, done}
и метания, когда генератор из газа):
function foo(x) {
var y, z, step = 0;
return function next(val) {
switch (step++) {
case 0: return x + 1; break;
case 1: y = 2 * val; return y/3; break;
case 2: z = val; return x + y + z; break;
default: throw "generator finished";
}
};
}
Затем:
iterator = foo(5);
iterator(); // 6
iterator(12); // 8
iterator(13); // 42