Suggest an editImprove this articleRefine the answer for “Generators and yield”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A generator is a function declared with `function*` that can pause its own execution and later resume from exactly the same place.** Calling it does not run the body: it returns an iterator object. Every `yield` pauses the function and hands a value out as `{ value, done }`, while the next `.next(value)` call resumes execution and pushes the passed value back in, right where the `yield` was standing. On top of that, `.return(value)` force-finishes the generator and `.throw(error)` throws an exception inside it. ```javascript function* counter() { yield 1; yield 2; } const gen = counter(); gen.next(); // { value: 1, done: false } ``` **Key point:** a generator sends values out through `yield` and takes values back in through the argument of `.next(value)`.Shown above the full answer for quick recall.Answer (EN)Image**A generator (`function*`) is a function that can pause its execution, hand out intermediate values and then continue from exactly the same place.** Formally, `function*` returns a special object, an iterator, which drives the execution of the function body. ## Theory ### TL;DR - `function*` declares a generator; calling it does not run the code, it returns an iterator object. - `yield` pauses execution, hands a value out as `{ value, done }` and waits for the next `.next()`. - `gen.next(value)` pushes a value back in: it becomes the result of the `yield` the generator is paused on. - `.return(value)` finishes the generator early, `.throw(error)` throws an exception inside it that can be caught with `try...catch`. - A generator automatically implements both the iterator protocol (`next()`) and the iterable protocol (`[Symbol.iterator]`), so it works in `for...of`. - Generators are perfect for lazy computation and infinite sequences: data is produced in portions, without building huge arrays. ### Quick example ```javascript function* myGenerator() { yield 1; yield 2; yield 3; } const gen = myGenerator(); console.log(gen.next()); // { value: 1, done: false } console.log(gen.next()); // { value: 2, done: false } console.log(gen.next()); // { value: 3, done: false } console.log(gen.next()); // { value: undefined, done: true } ``` ### How a generator is declared and what the call returns A generator is declared with an asterisk after the `function` keyword: ```javascript function* myGenerator() { yield 1; yield 2; yield 3; } ``` The key point: calling `myGenerator()` does not execute the function body. The call returns an iterator that you have to "crank" manually by calling `.next()`. Each such call runs the function up to the next `yield` and returns an object `{ value, done }`, where `value` is the value handed out and `done` tells you whether the function has already reached its end. An object or class method can be a generator too, with the asterisk in front of the name: `*items() { ... }`. An arrow function, however, can never be a generator. ### What yield does The `yield` operator does three things: 1. **Pauses execution** of the function exactly at this point. 2. **Hands a value out**, into the result of `.next()`. 3. Lets you **pass a value back in** on the following `.next()` call. **Example 1, a simple sequence:** ```javascript function* counter() { yield 1; yield 2; yield 3; } const gen = counter(); console.log(gen.next()); // { value: 1, done: false } console.log(gen.next()); // { value: 2, done: false } console.log(gen.next()); // { value: 3, done: false } console.log(gen.next()); // { value: undefined, done: true } ``` **Example 2, pauses between steps:** ```javascript function* steps() { console.log("Step 1"); yield; console.log("Step 2"); yield; console.log("Step 3"); } const gen = steps(); gen.next(); // "Step 1" gen.next(); // "Step 2" gen.next(); // "Step 3" ``` Here `yield` is used without a value, simply as a stopping point. ### How to pass a value back into a generator When you call `gen.next(value)`, that `value` lands inside the generator exactly where execution was paused by `yield`. In other words, the expression `yield "..."` evaluates to whatever you passed into the following `.next()`. **Example 3, passing a value back:** ```javascript function* dialog() { const name = yield "What is your name?"; const age = yield `Hello, ${name}! How old are you?`; yield `You are ${age} years old.`; } const gen = dialog(); console.log(gen.next()); // { value: "What is your name?", done: false } console.log(gen.next("Maria")); // { value: "Hello, Maria! How old are you?", done: false } console.log(gen.next(25)); // { value: "You are 25 years old.", done: false } console.log(gen.next()); // { value: undefined, done: true } ``` Step by step: - The first `next()` starts the generator and returns the value of the first `yield`. - The second `next("Maria")` inserts the string `"Maria"` where the first `yield` stood, so `name` receives that value. - The third `next(25)` inserts `25` in place of the second `yield`, so `age` equals `25`. ### Controlling a generator: next, return and throw The generator iterator has three control methods: | Method | What it does | | --- | --- | | `.next(value)` | Resumes execution and returns the next `{ value, done }` | | `.return(value)` | Force-finishes the generator, returns `{ value, done: true }` | | `.throw(error)` | Throws an exception inside the generator, catchable with `try...catch` | **Example 5, `return()` and `throw()`:** ```javascript function* process() { try { yield "Step 1"; yield "Step 2"; } catch (e) { console.log("Error:", e.message); } finally { console.log("Generator finished"); } } const gen = process(); console.log(gen.next()); // { value: "Step 1", done: false } console.log(gen.throw(new Error("Something went wrong"))); // Error: Something went wrong // Generator finished ``` The `finally` block also runs when the generator is stopped with `.return()`, which makes it the right place for resource cleanup. ### Generators as iterators, lazy and async sequences A generator automatically implements the iterator interface (`next()`) and the iterable interface (`[Symbol.iterator]`), so you can hand it straight to `for...of`, to spread or to destructuring: ```javascript function* numbers() { yield 1; yield 2; yield 3; } for (const n of numbers()) { console.log(n); // 1, 2, 3 } ``` **Example 4, an infinite sequence:** ```javascript function* infinite() { let i = 0; while (true) { yield i++; } } const gen = infinite(); console.log(gen.next().value); // 0 console.log(gen.next().value); // 1 console.log(gen.next().value); // 2 ``` This code does not hang, because values are computed lazily: the next number appears only when it is asked for through `.next()`. **Bonus, generators and asynchrony.** Before `async/await` existed, generators were exactly what people used for asynchronous code (through libraries such as `co`): ```javascript function* getData() { const user = yield fetch('/user'); const posts = yield fetch(`/posts?user=${user.id}`); return posts; } ``` `async/await` was later built on the very same idea; it is essentially an "automated generator" where the engine calls `.next()` for you once the promise settles. **Summary table:** | Concept | Description | | --- | --- | | `function*` | Generator declaration | | `yield` | Pauses execution and hands a value out | | `.next(value)` | Resumes execution, passing `value` in | | `.return(value)` | Finishes the generator | | `.throw(error)` | Throws an exception into the generator | | **Generator** | An iterator object whose execution can be paused and resumed | ### Common mistakes - **Thinking that calling `myGenerator()` runs the function body.** It only creates an iterator; the first line runs on the first `.next()`. - **Expecting the argument of the first `.next(value)` to land somewhere.** The first call only starts the generator, and the passed value is discarded, because there is no `yield` yet that could receive it. - **Mixing up the directions.** What goes out is the value to the right of `yield`; what comes in is the argument of the following `.next()`. - **Running an infinite generator through `for...of` without a `break`.** The loop never ends, because `done` never becomes `true`. - **Forgetting that a generator is single-use.** After `done: true` or after `.return()`, every further `.next()` gives `{ value: undefined, done: true }`; to walk the sequence again you need a new generator. - **Trying to declare a generator as an arrow function.** `function*` works only with regular functions and methods (`*method() {}`). - **Treating a generator as asynchronous by itself.** A plain generator is synchronous; asynchronous sequences need `async function*` and `for await...of`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.