class
FibonacciSequence
{
[
Symbol
.
iterator
]() {
let
a
=
0
,
b
=
1
;
return
{
next
() {
let
rval
=
{
value
:
b
,
done
:
false
};
b
+=
a
;
a
=
rval
.
value
;
return
rval
;
}
};
}
}
If we used an instance of
FibonacciSequence
with a
for...of
loop, we’ll end up with
an infinite loop…we’ll never run out of Fibonacci numbers! To prevent this, we’ll add
a
break
statement after 10 elements:
const
fib
=
new
FibonacciSequence
();
let
i
=
0
;
for
(
let
n
of
fib
) {
console
.
log
(
n
);
if
(
++
i
>
9
)
break
;
}
Generators
Generators are functions that use an iterator to control their execution. A regular
function takes arguments and returns a value, but otherwise the caller has no control
of it. When you call a function, you relinquish control to the function until it returns.
Not so with generators, which allow you to control the execution of the function.
Generators bring two things to the table: the first is the ability to control the execu‐
tion of a function, having it execute in discrete steps. The second is the ability to com‐
municate with the function as it executes.
A generator is like a regular function with two exceptions:
• The function can yield control back to the caller at any point.
• When you call a generator, it doesn’t run right away. Instead, you get back an iter‐
ator. The function runs as you call the iterator’s
next
method.
Generators are signified in JavaScript by the presence of an asterisk after the
func
tion
keyword; otherwise, their syntax is identical to regular functions. If a function is
a generator, you can use the
yield
keyword in addition to
return
.
Let’s look at a simple example—a generator that returns all the colors of the rainbow:
Generators | 179