recursal/MDN huggingface dataset:
async function
==============

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2017.

* Learn more
* See full compatibility
* Report feedback
**`async function`** 宣告被定義為一個回傳 `AsyncFunction` (en-US) 物件的*非同步函式* 。

你也可以使用 async function expression (en-US) 來定義一個*非同步函式*。

語法
--
```

async function name([param[, param[, ... param]]]) {
   statements
}
```

### 參數

`name`

函式名稱。

`param`

傳遞至函式的參數名稱。

`statements`

組成該函式主體的陳述。

### 回傳值

`AsyncFunction` (en-US) 物件，代表著一個非同步函式，該函式會執行該函式內的程式碼。

描述
--

當 `async` 函式被呼叫時，它會回傳一個 `Promise`。如果該 `async` 函式回傳了一個值，`Promise` 的狀態將為一個帶有該回傳值的 resolved。如果 `async` 函式拋出例外或某個值，`Promise` 的狀態將為一個帶有被拋出值的 rejected。

async 函式內部可以使用 `await` 表達式，它會暫停此 async 函式的執行，並且等待傳遞至表達式的 Promise 的解析，解析完之後會回傳解析值，並繼續此 async 函式的執行。

**備註：** `async/await` 函式的目的在於簡化同步操作 promise 的表現，以及對多個 `Promise` 物件執行某些操作。就像 `Promise` 類似於具結構性的回呼函式，同樣地，async/await 好比將 generator 與 promise 組合起來。

範例
--

### 簡單範例


```js
function resolveAfter2Seconds(x) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function add1(x) {
  const a = await resolveAfter2Seconds(20);
  const b = await resolveAfter2Seconds(30);
  return x + a + b;
}

add1(10).then((v) => {
  console.log(v); // prints 60 after 4 seconds.
});

async function add2(x) {
  const p_a = resolveAfter2Seconds(20);
  const p_b = resolveAfter2Seconds(30);
  return x + (await p_a) + (await p_b);
}

add2(10).then((v) => {
  console.log(v); // prints 60 after 2 seconds.
});
```


**警告：** 不要誤解 `Promise.all` 的 `await`

在 `add1` 裡，該執行為了第一個 `await` 而暫停了兩秒，接著為了第二個 `await` 又暫停了兩秒。在第一個計時器（timer）被觸發前，第二個計時器並不會被建立。而在 `add2` 裡，兩個計時器都被建立起來、也都執行 `await` 過了。這把它帶往了 resolve 所的 2 秒暫停、而不是 4 秒暫停。然而這兩個 `await` 呼叫都在連續運行，而非平行運行。`await` **並不是** `Promise.all` 的自動程式。如果你想讓兩個、甚至兩個以上的 `await` promises 同時執行（in parallel），你必須使用 `Promise.all`.

### 使用 async function 改寫 promise 鏈

一個 API 呼叫所回傳的 `Promise` 會導致一個 promise 鏈，將函式分隔成多個部份。考慮下列的程式碼：


```js
function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch((e) => {
      return downloadFallbackData(url); // returns a promise
    })
    .then((v) => {
      return processDataInWorker(v); // returns a promise
    });
}
```


它可以用一個簡單的 `async function` 來改寫成這樣：


```js
async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}
```


注意上方的範例，在 return 陳述中沒有使用 await 陳述，這是因為 async function 的回傳值隱含地被包裝於 `Promise.resolve` 之中。

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-async-function-definitions |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

參見
--

* `async function expression` (en-US)
* `AsyncFunction` (en-US) 物件
* `await`
* "Decorating Async Javascript Functions" on "innolitics.com"
export
======

用 **export** 可以指派函式、物件或變數，透過 `import` 宣告給外部檔案引用。

導出的模塊都會處於`嚴謹模式`，無論是否有所宣告。導出宣告無法使用嵌入式腳本（embedded script）。

語法
--
```

export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
// 用 var, const 也通
export let name1, name2, …, nameN;
export let name1 = …, name2 = …, …, nameN;

// 底下的 function 用 class, function* 也可以
export default expression;
export default function (…) { … }
export default function name1(…) { … }

export { name1 as default, … };
export * from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
```


`nameN`

外部檔案使用 `import` 時，用於辨認的名稱。

使用說明
----

有兩種使用 export 的方式，**named** 與 **default**。每個模組中可以有多個 named exports, 但只能有一個 default export。每種 export 都對應到一個先前說的語法。

* Named exports:

```js
// 前面已經宣告的函式可以這樣輸出
export { myFunction };

// 輸出常數
export const foo = Math.sqrt(2);
```

* 預設 export （一個 js 檔案只能有一個）:

```js
export default function () {}
// 或是 'export default class {}'
// 結尾不用分號
```


Named exports 在輸出多個值的時候很有用，在 import 的時候, 會強制根據使用相同的物件名稱.

但如果是 default export 則可以用任意的名字輸出.
```

export default k = 12; // 在test.js中這樣子寫

import m from './test' // 注意這邊因為 export default 的關係, 可以用任意名字 import 原先的k出來

console.log(m);        // will log 12
```


以下語法並不會導出所有被引入的模塊：
```

export * from …;
```


你必須額外引入它的預設輸出，再導出之：
```

import mod from "mod";
export default mod;
```

使用範例
----

### 輸出命名過的變數

模塊內可以這樣用：


```js
// module "my-module.js"
function cube(x) {
  return x \* x \* x;
}
const foo = Math.PI + Math.SQRT2;
var graph = {
  options: {
    color: "white",
    thickness: "2px",
  },
  draw: function () {
    console.log("From graph draw function");
  },
};
export { cube, foo, graph };
```


在另一個腳本就會變成這樣：


```js
//You should use this script in html with the type module ,
//eg ''<script type="module" src="demo.js"></script>",
//open the page in a httpserver,otherwise there will be a CORS policy error.
//script demo.js

import { cube, foo, graph } from "my-module";
graph.options = {
  color: "blue",
  thickness: "3px",
};
graph.draw();
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888
```

### 使用預設輸出

如果我們要輸出單獨的函式、物件、class 或當做 fallback 值來輸出的話，就可以用預設輸出：


```js
// module "my-module.js"
export default function cube(x) {
  return x \* x \* x;
}
```


外部檔案的 import 用法：


```js
import cube from "my-module";
console.log(cube(3)); // 27
```


Note 注意預設輸出不能使用 var, let , const。

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-exports |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

參見
--

* `import`
* ES6 in Depth: Modules, Hacks blog post by Jason Orendorff
* Axel Rauschmayer's book: "Exploring JS: Modules"
const
=====

Constants (常數) 有點像使用 `let` 所宣告的變數，具有區塊可視範圍。常數不能重複指定值，也不能重複宣告。嘗試一下
----

語法
--
```

const name1 = value1 [, name2 = value2 [, ... [, nameN = valueN]]];
```


`nameN`

常數的名稱，可以是任何合法的 identifier。

`valueN`

常數的值，可以是任何合法的 expression，包括 function expression。

描述
--

上述宣告建立一個常數，它的可視範圍可能是全域的，或是在它所宣告的區域區塊中。 和 `var` 變數不同的是，全域的常數不會變成 window 物件的屬性。常數必須要初始化；也就是說，你必須在宣告常數的同一個敘述式中指定這個常數的值。(這很合理，因為稍後就不能再變更常數的值了)

宣告 **`const`** 會對於它的值建立一個唯讀的參考。並不是說這個值不可變更，而是這個變數不能再一次指定值。例如，假設常數的內容(值)是個物件，那麼此物件的內容(物件的參數)是可以更改的。

所有關於 "temporal dead zone" 的狀況，都適用於 `let` and `const` 。

在相同的可視範圍內，常數不能和函數，變數具有相同名稱。

範例
--

以下範例展示常數的行為。請在你的瀏覽器中試試以下程式碼。


```js
// 注意: 常數可以宣告成大寫或小寫,
// 但習慣上使用全部大寫的字母。

// 定義一個常數 MY\_FAV 並賦予它的值為7
const MY\_FAV = 7;

// 這裡會發生錯誤 - Uncaught TypeError: Assignment to constant variable.
MY\_FAV = 20;

// MY\_FAV 是 7
console.log('我喜歡的數字是: ' + MY\_FAV);

// 嘗試重複宣告同名的常數，將會發生錯誤 - Uncaught SyntaxError: Identifier 'MY\_FAV' has already been declared
const MY\_FAV = 20;

// MY\_FAV 這個名稱已經保留給上面的常數, 所以這裡也會錯誤。
var MY\_FAV = 20;

// 這式子也會錯誤
let MY\_FAV = 20;

// 很重要，請注意區塊可視範圍的特性。
if (MY\_FAV === 7) {
    // 以下式子沒有問題，並且會建立一個名叫 MY\_FAV 的具有區塊可視範圍的變數。
    // (等同於使用 let 來宣告一個具有區塊可視範圍的非常數變數。)
    let MY\_FAV = 20;

    // MY\_FAV 現在變成 20
    console.log('我喜歡的數字是：' + MY\_FAV);

    // 這會將變數懸掛於全域，而導致錯誤。(與常數同名)
    var MY\_FAV = 20;
}

// MY\_FAV 仍然是 7
console.log('我喜歡的數字是：' + MY\_FAV);

// 發生錯誤 - Uncaught SyntaxError: Missing initializer in const declaration
const FOO;

// 常數的值可以是一個物件
const MY\_OBJECT = {'key': 'value'};

// 嘗試覆寫該物件將會發生錯誤 - Uncaught TypeError: Assignment to constant variable.
MY\_OBJECT = {'OTHER\_KEY': 'value'};

// 然而, 物件的屬性並沒有被保護,
// 所以，以下敘述式沒有問題。
MY\_OBJECT.key = 'otherValue'; // Use Object.freeze() to make object immutable

// 對陣列來說也是一樣
const MY\_ARRAY = [];
// 可以把項目加到陣列中。
MY\_ARRAY.push('A'); // ["A"]
// 然而，對這個變數指定新陣列，將會發生錯誤 - Uncaught TypeError: Assignment to constant variable.
MY\_ARRAY = ['B'];
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-let-and-const-declarations |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

參閱
--

* `var`
* `let`
* Constants in the JavaScript Guide
continue 語法
===========

`continue` 語法可用來重新開始 `while`、`do-while`、`for`、`label` 語法。

* 當你使用沒加標籤的 `continue` 時，他會終止這一次的最內層的 `while`、`do-while`、`for` 語法的反覆過程，並繼續執行下一次的反覆過程。與 `break` 語法相較之下，`continue` 不會終止整個循環的執行。在 `while` 循環中，他會跳回條件處。在 `for` 循環中，他會跳回遞增表達式。
* 當你使用加上標籤的 `continue` 時，他會跳到以 `label` 標記的循環語句。

`continue` 語法如下︰

1. `continue`
2. `continue label`
範例 1
----

以下範例示範加上 `continue` 語法的 `while` 循環，`continue` 語法會在 `i` 值為 3 時執行。因此，`n` 的值依序為 1、3、7、12。


```js
i = 0;
n = 0;
while (i < 5) {
  i++;
  if (i == 3) continue;
  n += i;
}
```

範例 2
----

已加上標籤的語法 `checkiandj` 內含已加上標籤的語法 `checkj`。如果遇到 `continue`，程式會終止 `checkj` 這一次的反覆過程，並開始下一次的反覆過程。每當遇到 `continue`，就會反覆執行 `checkj` 直到他的條件返回 false 為止。當返回 false 時，`checkiandj` 語句完成了餘數的計算，且 `checkiandj` 會反覆執行，直到他的條件返回為 false 為止。當返回 false 時，程式繼續執行 `checkiandj` 後面的語句。

如果 `continue` 有一個 `checkiandj` 標籤，程式就會從 `checkiandj` 語句的開始處繼續執行。


```js
checkiandj: while (i < 4) {
  document.write(i + "<br/>");
  i += 1;
  checkj: while (j > 4) {
    document.write(j + "<br/>");
    j -= 1;
    if (j % 2 == 0) continue checkj;
    document.write(j + " is odd.<br/>");
  }
  document.write("i = " + i + "<br/>");
  document.write("j = " + j + "<br/>");
}
```
return
======

**`return` 表達式**會終止函式執行，並指明函式呼叫器（function caller）要回傳的數值。

嘗試一下
----

語法
--
```

return [[expression]];
```


`expression`

要被回傳的表達式。如果省略了表達式，函式就會回傳 `undefined`。

敘述
--

如果在 function body 內宣告 `return` 的話，函式執行就會終止。如果指定數值的話，函式呼叫器就會回傳給定的數值。例如說，以下函式會回傳 `x` 參數的次方數。


```js
function square(x) {
  return x \* x;
}
var demo = square(3);
// demo will equal 9
```


如果省略了表達式，函式就會回傳 `undefined`。

以下所有的 return 宣告都會終止函式執行：


```js
return;
return true;
return false;
return x;
return x + y / 3;
```

### 自動插入分號

`return` 宣告會受自動插入分號（automatic semicolon insertion，ASI）影響。No line terminator is allowed between the `return` keyword and the expression.


```js
return;
a + b;
```


會因為 ASI 而變成：


```js
return;
a + b;
```


主控台會警告「unreachable code after return statement」（在 return 宣告後面有無法抵達的程式碼）。

**備註：** 從 Gecko 40 開始，如果主控台發現在 return 宣告後面有無法抵達的程式碼，就會顯示警告。

要避免 ASI 問題，可以添加括號：


```js
return a + b;
```

示例
--

### 終止函式

在到達呼叫 `return` 的地方後，函式會立即停止。


```js
function counter() {
  for (var count = 1; ; count++) {
    // 無限迴圈
    console.log(count + "A"); // 直到 5
    if (count === 5) {
      return;
    }
    console.log(count + "B"); // 直到 4
  }
  console.log(count + "C"); // 永不顯示
}

counter();

// 輸出：
// 1A
// 1B
// 2A
// 2B
// 3A
// 3B
// 4A
// 4B
// 5A
```

### 函式回傳

請參見閉包。


```js
function magic(x) {
  return function calc(x) {
    return x \* 42;
  };
}

var answer = magic();
answer(1337); // 56154
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-return-statement |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

參見
--

* 函式 (en-US)
* 閉包
label
=====

**標記陳述式**可以和 `break` 或 `continue` 語句一起使用。標記就是在一條陳述式前面加個可以引用的識別符號。

嘗試一下
----

**備註：** 標記的迴圈或程式碼區塊非常罕見。通常可以使用函式呼叫而不是使用迴圈跳轉。

語法
--
```

label :
   statement
```


`label`

任何不是保留字的 JavaScript 識別符號。

`statement`

一個 JavaScript 陳述式。`break` 可用於任何標記陳述式，而 `continue` 可用於循環標記陳述式。

描述
--

可使用一個標籤來唯一標記一個循環，然後使用 `break` 或 `continue` 陳述式來指示程式是否中斷循環或繼續執行。

需要注意的是 JavaScript **沒有** `goto` 陳述式，標記只能和 `break` 或 `continue` 一起使用。

在嚴格模式中，你不能使用 「`let`」 作為標籤名稱。它會拋出一個`SyntaxError` (en-US)（let 是一個保留的識別符號）。

範例
--

### 在 `for` 迴圈中使用帶標記的 `continue`


```js
var i, j;

loop1: for (i = 0; i < 3; i++) {
  //The first for statement is labeled "loop1"
  loop2: for (j = 0; j < 3; j++) {
    //The second for statement is labeled "loop2"
    if (i === 1 && j === 1) {
      continue loop1;
    }
    console.log("i = " + i + ", j = " + j);
  }
}

// Output is:
// "i = 0, j = 0"
// "i = 0, j = 1"
// "i = 0, j = 2"
// "i = 1, j = 0"
// "i = 2, j = 0"
// "i = 2, j = 1"
// "i = 2, j = 2"
// Notice how it skips both "i = 1, j = 1" and "i = 1, j = 2"
```

### 使用帶標記的 `continue` 陳述式

給定一組資料和一組測試，下面的例子可以統計通過測試的資料。


```js
var itemsPassed = 0;
var i, j;

top: for (i = 0; i < items.length; i++) {
  for (j = 0; j < tests.length; j++) {
    if (!tests[j].pass(items[i])) {
      continue top;
    }
  }

  itemsPassed++;
}
```

### 在 `for` 迴圈中使用帶標記的 `break`


```js
var i, j;

loop1: for (i = 0; i < 3; i++) {
  //The first for statement is labeled "loop1"
  loop2: for (j = 0; j < 3; j++) {
    //The second for statement is labeled "loop2"
    if (i === 1 && j === 1) {
      break loop1;
    }
    console.log("i = " + i + ", j = " + j);
  }
}

// Output is:
// "i = 0, j = 0"
// "i = 0, j = 1"
// "i = 0, j = 2"
// "i = 1, j = 0"
// Notice the difference with the previous continue example
```

### 使用帶標記 `break` 陳述式

給定一組資料和一組測試，下面的例子判斷是否所有的資料均通過了測試。


```js
var allPass = true;
var i, j;

top: for (i = 0; items.length; i++)
  for (j = 0; j < tests.length; i++)
    if (!tests[j].pass(items[i])) {
      allPass = false;
      break top;
    }
```

### 在標記的區塊中使用 `break`

你可以在程式碼區塊中使用標記，但只有 `break` 陳述式可以使用非迴圈的標記。


```js
foo: {
  console.log("face");
  break foo;
  console.log("this will not be executed");
}
console.log("swap");

// this will log:

// "face"
// "swap
```

### 標記的函式宣告式

從 ECMAScript 2015 開始，標準的函式宣告式現在對規範的 Web 相容性附件中的非嚴格程式碼進行了標準化。


```js
L: function F() {}
```


在嚴格模式中，這會拋出 `SyntaxError` (en-US) 例外：


```js
"use strict";
L: function F() {}
// SyntaxError: functions cannot be labelled
```


產生器函式既不能在嚴格模式中標記，也不能在非嚴格模式中標記：


```js
L: function\* F() {}
// SyntaxError: generator functions cannot be labelled
```

規格
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-labelled-statements |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

相關連結
----

* `break`
* `continue`
if...else
=========

當條件成立的時候會執行 if 陳述式裡的程式，而不成立時則執行另外一個陳述式。

嘗試一下
----

語法
--


```js
if (condition)
  statement1

// With an else clause
if (condition)
  statement1
else
  statement2
```


`condition`

一個成立或不成立的運算式。

`statement1`

如果 if 中的條件(conditions)為真時執行陳述式(statements)。陳述式可以為任何內容，包含巢狀式(nested)的 if 陳述。當要執行多行的陳述式(statements)時，使用區塊(block)將所要執行的陳述式包覆。如果不需要執行任何動作時，則不撰寫任何陳述式(empty statement)。

`statement2`

當件不成立時所執行的部份，當 else 被撰寫時才會被執行。可以是任何的陳述式，包含使用區塊(block)及巢狀(nested)的陳述。

描述
--

多重的 `if...else` 陳述式可以使用 `else if` 子句來建立一個巢狀結構的句子。要記住，在 JavaScript 中沒有 `elseif` (一個單字) 的語法可以用。


```js
if (condition1)
   statement1
else if (condition2)
   statement2
else if (condition3)
   statement3
// …
else
   statementN
```


將巢狀結構適當的排版後，我們能更了解其背後運作的邏輯：


```js
if (condition1)
  statement1
else
  if (condition2)
    statement2
  else
    if (condition3)
      statement3
// …
```


如果在一個條件式中有多個陳述要執行，可以使用區塊陳述式(`{ ... }`) 把所有陳述包在一起。 通常來說，無論如何都使用區塊陳述式是個很好的習慣，尤其是當你使用巢狀結構的 `if` 陳述式時，這會讓人更容易理解你的程式碼。


```js
if (condition) {
  statements1
} else {
  statements2
}
```


不要被Boolean物件中，布林值的 `true` 和 `false` 給混淆了。任何值只要不是 `false`、 `undefined`、 `null`、 `0`、 `NaN`，或者空字串 (`""`)，並且任何物件，包括其值是 `false`的布林物件 ，仍然會被條件陳述式視為條件成立。舉例而言：


```js
var b = new Boolean(false);
if (b) // this condition is truthy
```

實例
--

### 使用 `if...else`


```js
if (cipherChar === fromChar) {
  result += toChar;
  x++;
} else {
  result += clearChar;
}
```

### 使用 `else if`

要記得 JavaScript 沒有 `elseif` 可以使用。不過，你可以使用 `else` 和 `if`中間夾著空白的語法：


```js
if (x > 50) {
  /\* do something \*/
} else if (x > 5) {
  /\* do something \*/
} else {
  /\* do something \*/
}
```

### 條件表達式中的賦值

建議不要在條件表達式中直接對物件賦值，因為這會使人在瀏覽程式碼時很容易將賦值( assignment )與相等( equality )混淆。舉例而言，不要使用以下寫法：


```js
if ((x = y)) {
  /\* do the right thing \*/
}
```


如果你必須在條件表達式中使用賦值，最好 ˇ 的作法是以額外的括號包住賦值語句，如下所示：


```js
if (x = y) {
  // do something
}
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-if-statement |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

參見
--

* `block`
* `switch`
* `conditional operator`
for 語法
======

`for` 循環反覆執行直到指定的條件的求值為 false 為止。JavaScript 的 for 循環和 Java 和 C 的 for 循環很類似。`for` 語法如下︰


```js
for ([initialExpression]; [condition]; [incrementExpression]) statement;
```


執行 `for` 循環時，會執行以下步驟︰

1. 執行初始化表達式 `initialExpression`。這個表達式通常會初始化為 1 以上的計數器，不過也可以是任意複雜程度的表達式。也可以在表達式裡宣告變數。
2. 對 `condition` 表達式求值。如果 `condition` 的值為 true，就會執行循環語法。如果 `condition` 的值為 false，就終止 `for` 循環。如果完全省略 `condition` 表達式，條件就會被代入為 true。
3. 執行 `statement`。若要執行多個語句，就使用區塊語法（`{ ... }`）把這些語句群組化。
4. 執行更新表達式 `incrementExpression`，並回到第 2 步驟。
範例
--

以下函數內含 `for` 語法，計數至下拉式選單的已選擇選項的數目為止（Select 物件允許複選）。`for` 語法宣告變數 `i` 並以 0 初始化。他會檢驗 `i` 是否小於 `Select` 物件的選項數目，持續執行 `if` 語句，並在每一次循環之後以 1 遞增 `i`。


```html
<script type="text/javascript">
 //<![CDATA[

 function howMany(selectObject) {
 var numberSelected = 0;
 for (var i = 0; i < selectObject.options.length; i++) {
 if (selectObject.options[i].selected) numberSelected++;
 }
 return numberSelected;
 }

 //]]>
</script>
<form name="selectForm">
  <p>
    <strong>Choose some music types, then click the button below:</strong>
    <br />
    <select name="musicTypes" multiple="multiple">
      <option selected="selected">R&B</option>
      <option>Jazz</option>
      <option>Blues</option>
      <option>New Age</option>
      <option>Classical</option>
      <option>Opera</option>
    </select>
  </p>
  <p>
    <input
 type="button"
 value="How many are selected?"
 onclick="alert ('Number of options selected: ' + howMany(document.selectForm.musicTypes))" />
  </p>
</form>
```

* « 前頁
* 次頁 »
break
=====

**break 陳述句**會中斷目前的迭代、`switch` 或 `label` 陳述句，並將程式流程轉到被中斷之陳述句後的陳述句。

嘗試一下
----

語法
--
```

break [label];
```


`label`

可選的。欲中斷陳述句的標籤 (label) 識別。若不是要中斷迭代或 `switch`，則需加此參數。

說明
--

中斷陳述 `break` 可加上標籤 (label) 參數，使其跳出被標籤的陳述語句。此中斷陳述 `break` 必須被包含在被標籤的陳述語句中。被標籤的陳述語句可被添加於任一個區塊 (block (en-US)) 前，而非限定在迴圈陳述。

範例
--

下面函式包含一個中斷陳述 `break` ，當 `i` 值為 3 時，中斷 `while` 迴圈，並回傳 `3 * x` 。


```js
function testBreak(x) {
  var i = 0;

  while (i < 6) {
    if (i == 3) {
      break;
    }
    i += 1;
  }

  return i \* x;
}
```


The following code uses `break` statements with labeled blocks. A `break` statement must be nested within any label it references. Notice that `inner_block` is nested within `outer_block`.


```js
outer\_block: {
  inner\_block: {
    console.log("1");
    break outer_block; // breaks out of both inner\_block and outer\_block
    console.log(":-("); // skipped
  }
  console.log("2"); // skipped
}
```


The following code also uses `break` statements with labeled blocks but generates a Syntax Error because its `break` statement is within `block_1` but references `block_2`. A `break` statement must always be nested within any label it references.


```js
block\_1: {
  console.log('1');
  break block_2; // SyntaxError: label not found
}

block\_2: {
  console.log('2');
}
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-break-statement |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

參見
--

* `continue`
* `label`
* `switch`
while 語法
========

`while` 語法會執行他的語句，只要指定的條件的求值結果為 true。`while` 語法如下︰


```js
while (condition)
  statement
```


如果條件變成 false，就停止執行循環內部的 `statement`，並把控制權移交給循環後面的語句。

條件的測試會發生在執行循環裡的 `statement` 之前。如果返回的條件為 true，就會執行 `statement`，並再次測試條件。如果返回的條件為 false，就停止執行並把控制權移交給 `while` 後面的語句。

若要執行多個語句，就使用區塊語法（`{ ... }`）把這些語句群組化。

範例 1
----

以下 `while` 循環會一直反覆直到 `n` 小於 3 為止︰


```js
n = 0;
x = 0;
while (n < 3) {
  n++;
  x += n;
}
```


每一次的反覆，循環便會遞增 `n` 並且把 `n` 的值代入給 `x`。因此，`x` 和 `n` 持有下列的值︰

* 第一次循環以後︰`n` = 1、`x` = 1
* 第二次循環以後︰`n` = 2、`x` = 3
* 第三次循環以後︰`n` = 3、`x` = 6

第三次的循環完成以後，條件 `n` < 3 不再為 true，所以終止循環。

範例 2
----

應避免無限循環。確認循環裡的條件最終一定會變成 false。否則循環永遠不會終止。下面的 `while` 循環裡的語句將會永遠執行下去，因為條件永遠不會變成 false︰


```js
while (true) {
  alert("Hello, world");
}
```
區塊
==

總覽
--

區塊陳述用來組合零個或多個陳述。我們使用一對大括號 { } 以界定區塊。

| 陳述句 |
| --- |
| Implemented in | JavaScript 1.0 |
| ECMAScript edition | ECMA-262 1st edition |

語法
--
```

{
  陳述_1
  陳述_2
  ...
  陳述_n
}
```

### 參數

`陳述_1`, `陳述_2`, `陳述_n`

區塊陳述中的陳述句群。

說明
--

區塊陳述通常配合流程控制陳述（如 `if`、`for`、`while`）一併使用。

#### `var`

使用`var`區塊中定義的變數，其存取範圍是整個整個函式或是腳本，即為 Execution Context 的範圍中。


```js
var x = 1;
{
  var x = 2;
}
alert(x); // outputs 2
```


輸出結果是 2。因為 var 是宣告於整個腳本範圍中。

#### `let` 和 `const`

當使用`let`或是`const`進行宣告時，其存取範圍是只有本身定義的區塊中。


```js
let x = 1;
{
  let x = 2;
}
console.log(x); // logs 1
```


#### `function`

當 function 被呼叫時，會建立此 function 的 Execution Context，因此在 function 區塊使用`var`整個 function 區塊中都可對其進行存取。


```js
function foo() {
  {
    var a = "var";
    {
      let a = "let";
      console.log(a); // let
    }
  }
  console.log(a); // var
}
foo();
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-block |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.
其餘參數
====

**其餘參數（rest parameter）** 語法可以讓我們表示不確定數量的參數，並將其視為一個陣列。

語法
--


```js
function f(a, b, ...theArgs) {
  // ...
}
```

描述
--

如果函式的最後一個命名參數以 `...` 開頭，它會被視為一個陣列。該陣列的元素會被置於索引從 `0`（含）到的 `theArgs.length`（不含）位置，並且被視為一個函式的參數。

在上面的範例中，`theArgs` 會將函式 f 中第三個(含)以後的參數收集起來。

### 其餘參數和 `arguments` 物件的差異

以下是其餘參數和 `arguments 物件`三個主要的差異：

* 其餘參數是 `arguments` 物件被傳入到函式的時候，還沒被指定變數名稱的引數。
* `arguments` 物件不是一個實際的陣列，而 rest parameter 是陣列的實體，即 `sort`、`map`、`forEach` (en-US) 或 `pop` 可以直接在其餘參數被調用。
* `arguments` 物件自身有額外的功能，例如 `callee` 屬性。
### 將參數轉成陣列

其餘參數被介紹作為取代用 arguments 寫的範例程式。


```js
// 在有其餘參數之前，你可能見過下面的程式碼：
function f(a, b) {
  var args = Array.prototype.slice.call(arguments, f.length); // f.length 表示 arguments 的數量

  // …
}

// 現在可以寫成這樣

function f(a, b, ...args) {}
```

### 解構其餘參數 rest parameters

其餘參數可以被解構，換句話說，可以把這個陣列解開，並將各個元素取出成為個別的變數。請參考解構賦值。


```js
function f(...[a, b, c]) {
  return a + b + c;
}

f(1); // NaN (b 和 c 都是 undefined)
f(1, 2, 3); // 6
f(1, 2, 3, 4); // 6 (第四個參數不會被解構，因為解構式只有三個定義好的變數名稱)
```

範例
--

因為 `theArgs` 是一個陣列，所以它會有 `length` 屬性，作為表示參數數量：


```js
function fun1(...theArgs) {
  console.log(theArgs.length);
}

fun1(); // 0
fun1(5); // 1
fun1(5, 6, 7); // 3
```


在接下來的範例中，其餘參數被用來收集第一個之後的所有引數並存在陣列中。 在這個陣列裡的每個元素(數字)，都會和第一個參數相乘後取代原本的元素，最後再將取代元素後的陣列回傳。


```js
function multiply(multiplier, ...theArgs) {
  return theArgs.map(function (element) {
    return multiplier \* element;
  });
}

var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
```


下列範例展示 `Array` 的方法可以在其餘參數上被使用，但 `arguments` 則不行。


```js
function sortRestArgs(...theArgs) {
  var sortedArgs = theArgs.sort();
  return sortedArgs;
}

console.log(sortRestArgs(5, 3, 7, 1)); // 顯示 1, 3, 5, 7

function sortArguments() {
  var sortedArgs = arguments.sort();
  return sortedArgs; // 因為前一行會因為 arguments 沒有sort()這個方法而造成TypeError，所以永遠不會執行此行。
}

console.log(sortArguments(5, 3, 7, 1)); // 會拋出 TypeError (arguments.sort is not a function)
```


為了要在 `arguments` 物件上使用 `Array` 的方法，可以將它轉換成真的 `Array` 實體，或者以 `apply()` 直接調用需要的方法。


```js
function sortArguments() {
  var args = Array.from(arguments);
  var sortedArgs = args.sort();
  return sortedArgs;
}
console.log(sortArguments(5, 3, 7, 1)); // 顯示 1, 3, 5, 7
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-function-definitions |

瀏覽器相容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

參見
--

* Spread operator (en-US) (also 『`...`』)
* Arguments object (en-US)
* Array
* Functions (en-US)
* Original proposal at ecmascript.org
* JavaScript arguments object and beyond
* Destructuring assignment