Suggest an editImprove this articleRefine the answer for “The yield operator in generators”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`yield` is an operator that returns a value out of a generator function and pauses its execution until the next `.next()` call.** When the generator reaches a `yield` it freezes; the following `.next()` resumes work right after the `yield` where it stopped. It is a kind of temporary `return`: it hands a value out without finishing the function. ```javascript function* seq() { yield 'A'; yield 'B'; } const it = seq(); console.log(it.next().value); // "A" console.log(it.next().value); // "B" console.log(it.next().done); // true ``` **Key point:** `yield` only works inside `function*`, it makes evaluation lazy and the exchange two way through `next(value)`, and `yield*` delegates execution to another generator.Shown above the full answer for quick recall.Answer (EN)Image**`yield` is an operator that returns a value out of a generator function and pauses its execution until the next `.next()` call.** When the generator reaches a `yield` it freezes, and the following `.next()` resumes work right after the `yield` where it stopped. ## Theory ### TL;DR - `yield` hands a value out in the `value` field and stops the function where it stands. - The next `.next()` continues execution from the line after that `yield`. - It is a temporary `return`: the value is returned, but the function is not finished. - `next(value)` passes a value back in: it becomes the result of the `yield` expression. - `yield*` delegates execution to another generator or to any iterable object. - Thanks to `yield` evaluation is lazy: values are produced only on demand. ### Quick example ```javascript function* gen() { console.log('Before the first yield'); yield 1; console.log('Between the yields'); yield 2; console.log('After the second yield'); } const it = gen(); console.log(it.next()); // { value: 1, done: false } console.log(it.next()); // { value: 2, done: false } console.log(it.next()); // { value: undefined, done: true } ``` Step by step: 1. `gen()` returns an iterator object, the function has not started yet. 2. `it.next()` starts the function, it runs to `yield 1`, returns `{ value: 1 }` and freezes. 3. The next `it.next()` continues from the very same place, after `yield 1`. 4. After the second `yield` the generator freezes again. 5. When `done: true` arrives, the generator has finished its work. ### yield as a temporary return ```javascript function* seq() { yield 'A'; yield 'B'; yield 'C'; } const it = seq(); console.log(it.next().value); // "A" console.log(it.next().value); // "B" console.log(it.next().value); // "C" console.log(it.next().done); // true ``` The difference from `return` is fundamental: `return` finishes the function for good, while `yield` only hands out an intermediate value and leaves the function alive, with all of its local variables and its execution position intact. ### Passing a value back in with next(value) `yield` does not only send data out, it can also take a value back in on the following `.next(value)` call. ```javascript function* dialog() { const name = yield 'What is your name?'; yield `Hello, ${name}!`; } const chat = dialog(); console.log(chat.next().value); // "What is your name?" console.log(chat.next('Maria').value); // "Hello, Maria!" ``` - The first `next()` started the generator and ran it to the first `yield`. - The second `next('Maria')` passed `'Maria'` into the generator, and that value landed in `const name`. ### Finishing a generator: return() and throw() A generator finishes when it reaches the end of its body, or if you call `iterator.return(value)`. In the second case it immediately reports `done: true`. ```javascript function* numbers() { yield 1; yield 2; } const it = numbers(); console.log(it.next()); // { value: 1, done: false } console.log(it.return('stop')); // { value: 'stop', done: true } console.log(it.next()); // { value: undefined, done: true } ``` In the same way you can inject an error straight into the generator, at the point of the current `yield`, and catch it there with an ordinary `try/catch`: ```javascript function* gen() { try { yield 1; } catch (e) { console.log('Error caught:', e.message); } } const it = gen(); it.next(); it.throw(new Error('Something went wrong')); // Error caught: Something went wrong ``` ### yield*: delegating to another generator Sometimes one generator needs to hand control over to another. That is what `yield*` is for. ```javascript function* inner() { yield 'B'; yield 'C'; } function* outer() { yield 'A'; yield* inner(); // hands control over to another generator yield 'D'; } for (const val of outer()) { console.log(val); } ``` Output: ```javascript A B C D ``` In essence `yield*` is a nested loop: just yield every value of the other generator. It works not only with generators but with any iterable object, for example `yield* [1, 2, 3]`. ### Laziness of evaluation `yield` is what makes generators lazy: values are computed only on demand, not in advance. ```javascript function* range(start, end) { for (let i = start; i <= end; i++) { console.log('Generating', i); yield i; } } for (const num of range(1, 3)) { console.log('Received:', num); } ``` Output: ```javascript Generating 1 Received: 1 Generating 2 Received: 2 Generating 3 Received: 3 ``` You can see that the generator creates values as they are needed rather than holding the whole range at once. Summary: | Feature | Description | | --- | --- | | What it does | Pauses execution and returns a value | | Resuming | Through `.next()` | | Can take values back in | Yes, `next(value)` | | Can be finished | Through `return()` | | Can be delegated | Through `yield*` | | Evaluation | Lazy | | Only works inside | `function*` (generators) | ### Common mistakes - **Using `yield` outside a generator.** In a regular or arrow function that is a syntax error, `yield` only exists inside `function*`. - **Expecting the first `next(value)` to deliver a value.** The first call only runs the body to the first `yield`, so the argument you pass goes nowhere. - **Confusing `yield` with `yield*`.** `yield inner()` hands out the generator object itself as a single value, while `yield* inner()` hands out all of its values one by one. - **Thinking `yield` finishes the function.** It does not, it only pauses it; `return` or reaching the end of the body finishes it. - **Forgetting a `try/catch` around `yield`.** Without one, `it.throw()` simply terminates the generator and rethrows the error outwards. - **Building the whole array up front where a `yield` belongs.** That throws away the main benefit of generators, laziness and lower memory use.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.