I was expecting 4 to be part of the sequence array, so why is it skipped?
function* generate() {
yield 1;
yield 2;
yield 3;
return 4
}
let sequence = [...generate()];
console.log(sequence); // 1, 2, 3
The return
value of a generator function is not considered part of the sequence. It is returned from the last .next()
call as {done: true, value:…}
, where done: true
implies that the sequence was completed and .next()
should not be called again.
Why is that so, why couldn't we just yield the last value with the done
flag set to true
? Because then we could not represent an empty sequence with an iterator - the first .next()
call would already lead to at least one value.1
So usually, generator functions do not return anything (but undefined
), and all sequence values are yielded with the same syntax - there is no weird special syntax for the last value2:
function* generate() {
yield 1;
yield 2;
yield 3;
yield 4;
}
1: Other languages do this differently. There, iterators have a separate .hasNext()
method that is called before .next()
, or their .next()
method either returns a value or throws a StopIteration
exception. They don't have any "final value".
2: Having to know beforehand that a value is that last and using return
instead of
yield
for it would make the logic for dynamically generated sequences much more complicated.