Mastering ES6 Yield: How Generators Pause and Resume Execution
This article explains the ES6 yield keyword, its role in generator functions, how the .next() method controls execution flow, how parameters affect yielded values, and provides practical examples to help JavaScript developers master asynchronous iteration.
Introduction
ES6 dramatically changed JavaScript, and the yield keyword is one of its most disruptive features. When I first encountered yield in Ember.js, I didn’t understand its purpose, but after studying ES6 I finally grasped its basic idea and was eager to try it out.
Keyword yield
yieldis a keyword, not a function. Like
return, it signals a program state:
returntells the program what value to output and ends execution, while
yieldtells the program the current state value and pauses execution at that point.
Because
yieldis a command‑type keyword, its syntax is simple: the expression after
yieldis optional, and the return value is a state object. Although it can be viewed as an operator, its primary purpose is pausing and resuming, not calculation.
Generator Functions
ES6 introduced Generators, which I translate as “iterator functions”. A Generator’s main purpose is to produce an iterator. To declare a Generator, place an asterisk (*) between the
functionkeyword and the function name.
Only inside a Generator does
yieldmake sense; outside it has no effect, just as a shark would be useless on land.
Generators do not run immediately after declaration; they start running only when their
.next()method is called.
The .next() Method
Calling
f.next()starts execution of the Generator
f. When the interpreter reaches a
yieldstatement, it pauses and returns an object
{value: ..., done: false}. The
valuefield holds the result of the yielded expression, and
doneindicates whether the iterator has finished.
If
.next()is called again, execution resumes after the previous
yield. When a
returnstatement is encountered, the iterator ends and
donebecomes
true.
When the code reaches
<code>yield '', execution stops; any subsequent arithmetic statements are not executed until the next
.next()call.
Methods like
for...of,
Array.from, and the spread operator rely on the iterator protocol, so without Generators these constructs would not work. In Babel, additional polyfills are required to support Generators.
Parameters of .next()
The argument passed to
.next(value)replaces the value of the previous
yield. For example, after the first
.next()pauses at
yield x + 1, calling
foo.next(3)substitutes
3for
x + 1, making
y = 3. Subsequent yields behave similarly.
Two common questions:
Why can’t the first
.next()call receive a parameter? Because there is no previous
yieldto replace.
Why are parentheses sometimes required after
yield? Without parentheses, the following
+operation would be lost, changing the result.
Treating yield as a Variable
When a parameter is passed to
.next(), it replaces the entire expression following the corresponding
yield. This allows creative uses such as building string templates by treating
yieldlike a placeholder variable.
Summary
Key points about
yield:
It can only be used inside Generator functions.
Calling
.next()runs the Generator until the next
yield, then pauses.
The return value of
.next()is an object
{value, done}.
Subsequent
.next()calls resume execution after the previous
yield.
When
.next()receives an argument, that argument replaces the expression of the preceding
yield.
Finally,
for...ofiterates over the values produced by a Generator by repeatedly calling
.next()and using each
valueas the loop variable.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.