> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/web/js/iteration/generator/func/yield.md).

# yield

* [JS](/web/js.md) ⟩ [objects](/web/js/val/obj.md) ⟩ [built-in](/web/js/val/builtin.md) ⟩ [Generator](/web/js/iteration/generator.md) ⟩ [generator function](/web/js/iteration/generator/func.md) ⟩ yield
* [JS](/web/js.md) ⟩ [statement](/web/js/grammar/statement.md) ⟩ [control flow](/web/js/grammar/statement/flow.md) ⟩ [jump](/web/js/grammar/statement/flow/jump.md) ⟩ yield

{% hint style="success" %} <mark style="color:yellow;">**(**</mark>[expression](/web/js/grammar/statement/expr.md)<mark style="color:yellow;">**)**</mark>

(used only in generator functions) to produce the <mark style="color:yellow;">**next value**</mark> without returning.
{% endhint %}

{% tabs %}
{% tab title="🧨 雷區" %}
{% hint style="danger" %} <mark style="color:blue;">yield</mark> and [yield\*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield*) [operator](/web/js/grammar/op.md) can <mark style="color:red;">**only**</mark> be used <mark style="color:yellow;">**within**</mark> [generator function](/web/js/iteration/generator/func.md)s❗️
{% endhint %}

* replit：[yield must be in generator functions](https://replit.com/@pegasusroe/yield-must-in-generator-function#index.js)

```javascript
// this seems like a generator function, but there's a catch ...
function* sequence(...iterables) {

    // --------------------------------------------------------------
    // ⭐ `yield/yield*` only available within generator functions❗
    // --------------------------------------------------------------
    
    // ❌ but this `yield*` is within an "arrow function"❗
    //
    //                 ╭─── 🔸 arrow function ───╮
    iterables.forEach( iterable => yield* iterable );
    //                             ^^^^^^
    // ⛔ ReferenceError: yield is not defined 
    
}
```

{% endtab %}

{% tab title="⭐️ 重點" %}
{% hint style="info" %} <mark style="color:yellow;">**the**</mark> [value](/web/js/val.md) <mark style="color:yellow;">**of the**</mark><mark style="color:yellow;">**&#x20;**</mark><mark style="color:yellow;"><mark style="color:red;">**current**<mark style="color:red;"></mark> [yield](/web/js/iteration/generator/func/yield.md)

* is <mark style="color:yellow;">**the**</mark> [argument](/web/js/val/func/argument.md) <mark style="color:yellow;">**to the**</mark>**&#x20;**<mark style="color:red;">**next call**</mark>**&#x20;**<mark style="color:yellow;">**of**</mark>  [next()](/web/js/iteration/iterator/next.md) (👉 see： [#fan-li](#fan-li "mention"))
* when the "[expression](/web/js/grammar/statement/expr.md) <mark style="color:yellow;">**after**</mark>**&#x20;**<mark style="color:purple;">**yield**</mark>" is <mark style="color:yellow;">**evaluated**</mark> and <mark style="color:yellow;">**yielded**</mark>, the execution of the <mark style="color:yellow;">**generator code**</mark>**&#x20;**<mark style="color:red;">**stops right there**</mark>, and the <mark style="color:yellow;">**value**</mark> of the "<mark style="color:purple;">**yield expression**</mark>" itself is still <mark style="color:blue;">**undefined**</mark> and waiting for the <mark style="color:red;">**next call**</mark> of [next()](/web/js/iteration/iterator/next.md) to <mark style="color:yellow;">**send it in**</mark>. (will remain <mark style="color:blue;">**undefined**</mark> if there's <mark style="color:red;">**no further**</mark> [next()](/web/js/iteration/iterator/next.md) call any more)
* can be considered as a <mark style="color:yellow;">**new starting point**</mark> for the <mark style="color:orange;">**next call**</mark> of [next()](/web/js/iteration/iterator/next.md).
  {% endhint %}
  {% endtab %}

{% tab title="🗺️ 圖表" %} <img src="https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2FHD46fUd2ti328InwY3EU%2Fvalue.of.yield.expr.svg?alt=media&amp;token=8a2ba13f-909e-4d8b-9019-9f5b2182c159" alt="value of yield expression vs. the next() method" class="gitbook-drawing">
{% endtab %}

{% tab title="💈範例" %}

* replit：[value of yield expression (2)](https://replit.com/@pegasusroe/value-of-yield-expr-2#index.js)

```javascript
const { log } = console;

// generator code
function* ints() {

    // argument to the `next(arg)` method
    // ---------------------------------------------
    // `arg`:
    //    • is the "value" of PREVIOUS "yield expression".
    //    • is ignored in the first call of next().
    //      (since there's NO previous yield expression)
    //    • can be considered a "new starting point" for
    //      the "current" call of next() method.
    //      (except for the first call, in which `arg` is ignored)

                                    // #1 next() call
                                    // ---------------
    //                    ╭─1─╮     //   1. value for #1 call
    const arg2   =  yield   1  ;    //      (execution stops at Y.E.)
    //   ╰─ 2 ─╯   ╰── Y.E. ──╯     //   Y.E. : yield expression
    
                                    // #2 next() call
                                    // --------------
                                    //   2. argument sent in by #2 call
    //                   ╭── 3 ──╮  //   3. value for #2 call
    const arg3   = yield [2, arg2]; //      (execution stops at Y.E.)
    //   ╰─ 4 ─╯   ╰──── Y.E. ───╯  // 

                                    // #3 next() call
                                    // --------------
    //     ╭── 5 ──╮                //   4. argument sent in by #3 call        
    return [3, arg3];               //   5. "done" value for #3 call
                                    //      (the iteration is finished)
}

// table settings
const headers = ['   ', 'value', 'done'];
const n = headers.length;    // number of columns
const [colWidth, pad, ext] = [5, 1, 0];
const line = '-'.repeat(colWidth*n + pad*(n-1) + ext);
log(`    value  done`);
log(line);

// log iteration result
function logResult(r, i) {
    let value = r.value === undefined ? 'x' : String(r.value);
    value = value.padEnd(5, ' ');
    const done = (r.done ? '✅' : '❌').padEnd(4, ' ');
    log(`#${i}:  ${value}  ${done}`);
}

// main
let it = ints(); 

const r1 = it.next('a');    // #1 next() call
logResult(r1, 1);

const r2 = it.next('b');    // #2 next() call
logResult(r2, 2);

const r3 = it.next('c');    // #3 next() call
logResult(r3, 3);

// output:
//
//     value  done
// -----------------
// #1:  1      ❌   
// #2:  2,b    ❌   
// #3:  3,c    ✅ 
```

{% endtab %}

{% tab title="📗 參考" %}

* [ ] JS.info ⟩ ["yield" is a two-way street](https://javascript.info/generators#yield-is-a-two-way-street)
* [ ] [JavaScript: The Definitive Guide](/web/master/ref/javascript-the-definitive-guide.md) ⟩ 5.5.5 yield
  {% endtab %}

{% tab title="📘 手冊" %}

* [ ] [yield](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield)
  {% endtab %}
  {% endtabs %}
