---
title: function*
slug: Web/JavaScript/Reference/Statements/function*
tags:
  - ECMAScript 2015
  - Function
  - Iterator
  - JavaScript
  - Statement
translation_of: Web/JavaScript/Reference/Statements/function*
---
<div>{{jsSidebar("Statements")}}</div>

<p><code><strong>function*</strong></code> 宣告式(<code>function</code> 關鍵字後面跟著一個星號)定義了一個<em>生成器函式(generator function)</em>,他會回傳一個{{jsxref("Global_Objects/Generator","生成器(Generator)")}}物件。</p>

<div>{{EmbedInteractiveExample("pages/js/statement-functionasterisk.html")}}</div>



<div class="noinclude">
<p>你可以透過 {{jsxref("GeneratorFunction")}} 建構式來定義生成器函式。</p>
</div>

<h2 id="語法">語法</h2>

<pre class="syntaxbox">function* <em>name</em>([<em>param</em>[, <em>param</em>[, ... <em>param</em>]]]) {
   <em>statements</em>
}
</pre>

<dl>
 <dt><code>name</code></dt>
 <dd>函式名稱。</dd>
 <dt><code>param</code></dt>
 <dd>要被傳入函式的引數名稱,一個函式最多可以擁有 255 個引數。</dd>
 <dt><code>statements</code></dt>
 <dd>statements 構成了函式內容的陳述式。</dd>
</dl>

<h2 id="描述">描述</h2>

<p>生成器是可以離開後再次進入的函式。在兩次進入之間,生成器的執行狀態(變數綁定狀態)會被儲存。</p>

<p>呼叫生成器函式並不會讓裡面的程式碼立即執行,而是會回傳一個針對該函式的<a href="/zh-TW/docs/Web/JavaScript/Reference/Iteration_protocols#iterator">迭代器(iterator)</a>物件。當呼叫迭代器的 <code>next()</code> 方法時,生成器函式將會執行到遭遇的第一個 {{jsxref("Operators/yield", "yield")}} 運算式,該運算式給定的值將從迭代器中回傳,如果是 {{jsxref("Operators/yield*", "yield*")}} 則會交給另一個生成器函式處理。<code>next()</code> 方法回傳一個物件,該物件有 <code>value</code> 屬性,包含了產生的數值,還有 <code>done</code> 屬性,為布林值,指出該生成器是否產出最後的數值。呼叫 <code>next()</code> 方法如果帶有一個參數,將會讓先前暫停的生成器函式恢復執行,以該參數值取代先前暫停的 <code>yield</code> 陳述式。</p>

<p>生成器中的 <code>return</code> 陳述式被執行時,會讓生成器 <code>done</code> 狀態為真。若有數值被返回的動作帶回,將是放在 <code>value</code> 傳回的。已返回的生成器不會再產生任何數值。</p>

<h2 id="範例">範例</h2>

<h3 id="簡單例子">簡單例子</h3>

<pre class="brush: js">function* idMaker() {
  var index = 0;
  while (index &lt; index+1)
    yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
// ...</pre>

<h3 id="yield*_的範例">yield* 的範例</h3>

<pre class="brush: js">function* anotherGenerator(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function* generator(i) {
  yield i;
  yield* anotherGenerator(i);
  yield i + 10;
}

var gen = generator(10);

console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
</pre>

<h3 id="傳入引數至生成器">傳入引數至生成器</h3>

<pre class="brush: js">function* logGenerator() {
  console.log(0);
  console.log(1, yield);
  console.log(2, yield);
  console.log(3, yield);
}

var gen = logGenerator();

// the first call of next executes from the start of the function
// until the first yield statement
gen.next();             // 0
gen.next('pretzel');    // 1 pretzel
gen.next('california'); // 2 california
gen.next('mayonnaise'); // 3 mayonnaise
</pre>

<h3 id="生成器中的回傳陳述式">生成器中的回傳陳述式</h3>

<pre class="brush: js">function* yieldAndReturn() {
  yield "Y";
  return "R";
  yield "unreachable";
}

var gen = yieldAndReturn()
console.log(gen.next()); // { value: "Y", done: false }
console.log(gen.next()); // { value: "R", done: true }
console.log(gen.next()); // { value: undefined, done: true }
</pre>

<h3 id="生成器無法被建構">生成器無法被建構</h3>

<pre class="brush: js example-bad">function* f() {}
var obj = new f; // throws "TypeError: f is not a constructor"</pre>

<h3 id="以表達式定義生成器">以表達式定義生成器</h3>

<pre><code>const foo = function* () { yield 10; yield 20; };
const bar = foo();console.log(bar.next()); // {value: 10, done: false}</code></pre>

<p> </p>

<h2 id="規範">規範</h2>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName('ES2015', '#', 'function*')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Initial definition.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES2016', '#', 'function*')}}</td>
   <td>{{Spec2('ES2016')}}</td>
   <td>Changed that generators should not have [[Construct]] trap and will throw when used with <code>new</code>.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#', 'function*')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td> </td>
  </tr>
 </tbody>
</table>

<h2 id="瀏覽器相容性">瀏覽器相容性</h2>

<div>


<p>{{Compat("javascript.statements.generator_function")}}</p>
</div>

<h2 id="Firefox_規範註記">Firefox 規範註記</h2>

<h4 id="Generators_and_iterators_in_Firefox_versions_before_26">Generators and iterators in Firefox versions before 26</h4>

<p>Older Firefox versions implement an older version of the generators proposal. In the older version, generators were defined using a regular <code>function</code> keyword (without an asterisk) among other differences. See <a href="/en-US/docs/Web/JavaScript/Reference/Statements/Legacy_generator_function">Legacy generator function </a>for further information.</p>

<h4 id="IteratorResult_object_returned_instead_of_throwing"><code>IteratorResult</code> object returned instead of throwing</h4>

<p>Starting with Gecko 29 {{geckoRelease(29)}}, the completed generator function no longer throws a {{jsxref("TypeError")}} "generator has already finished". Instead, it returns an <code>IteratorResult</code> object like <code>{ value: undefined, done: true }</code> ({{bug(958951)}}).</p>

<h2 id="參見">參見</h2>

<ul>
 <li>{{jsxref("Operators/function*", "function* expression")}}</li>
 <li>{{jsxref("GeneratorFunction")}} object</li>
 <li><a href="/zh-TW/docs/Web/JavaScript/Reference/Iteration_protocols">迭代協議</a></li>
 <li>{{jsxref("Operators/yield", "yield")}}</li>
 <li>{{jsxref("Operators/yield*", "yield*")}}</li>
 <li>{{jsxref("Function")}} object</li>
 <li>{{jsxref("Statements/function", "function declaration")}}</li>
 <li>{{jsxref("Operators/function", "function expression")}}</li>
 <li>{{jsxref("Functions_and_function_scope", "Functions and function scope")}}</li>
 <li>Other web resources:
  <ul>
   <li><a href="http://facebook.github.io/regenerator/">Regenerator</a> an ES2015 generator compiler to ES5</li>
   <li><a href="http://www.youtube.com/watch?v=qbKWsbJ76-s">Forbes Lindesay: Promises and Generators: control flow utopia -- JSConf EU 2013</a></li>
   <li><a href="https://github.com/mozilla/task.js">Task.js</a></li>
   <li><a href="https://github.com/getify/You-Dont-Know-JS/blob/master/async%20%26%20performance/ch4.md#iterating-generators-asynchronously">Iterating generators asynchronously</a></li>
  </ul>
 </li>
</ul>