JavaScript 參考文件 - JavaScript

JavaScript 參考文件
===============

在 MDN 的 JavaScript 分區中，這一部分被作爲 Javascript 的資料庫。閱讀關於該參考 (en-US)以了解更多。

全域物件
----

本章節記錄了所有 JavaScript 標準內建物件 以及其方法與屬性。

### 數值屬性

* `Infinity`
* `NaN`
* `undefined` (en-US)
* `globalThis` (en-US)
### 函數屬性

* `eval()` (en-US)
* `isFinite()` (en-US)
* `isNaN()`
* `parseFloat()` (en-US)
* `parseInt()`
* `decodeURI()` (en-US)
* `decodeURIComponent()` (en-US)
* `encodeURI()` (en-US)
* `encodeURIComponent()` (en-US)
### 基礎物件

* `Object` (en-US)
* `Function` (en-US)
* `Boolean`
* `Symbol` (en-US)
### Error

* `Error` (en-US)
* `AggregateError` (en-US)
* `EvalError` (en-US)
* `InternalError` (en-US)
* `RangeError`
* `ReferenceError` (en-US)
* `SyntaxError` (en-US)
* `TypeError` (en-US)
* `URIError`
### 數字與日期

* `Number`
* `BigInt`
* `Math`
* `Date`
### 文字處理

* `String`
* `RegExp` (en-US)
### 具索引的集合

* `Array`
* `Int8Array` (en-US)
* `Uint8Array` (en-US)
* `Uint8ClampedArray` (en-US)
* `Int16Array` (en-US)
* `Uint16Array` (en-US)
* `Int32Array` (en-US)
* `Uint32Array` (en-US)
* `Float32Array` (en-US)
* `Float64Array` (en-US)
* `BigInt64Array` (en-US)
* `BigUint64Array` (en-US)
### 具鍵值的集合

* `Map`
* `Set`
* `WeakMap` (en-US)
* `WeakSet` (en-US)
### 結構化資料

* `ArrayBuffer`
* `SharedArrayBuffer` (en-US)
* `Atomics` (en-US)
* `DataView` (en-US)
* `JSON`
### 控制抽象化物件

* `Promise`
* `Generator` (en-US)
* `GeneratorFunction` (en-US)
* `AsyncFunction` (en-US)
### Reflection

* `Reflect` (en-US)
* `Proxy` (en-US)
### 國際化

* `Intl` (en-US)
* `Intl.Collator` (en-US)
* `Intl.DateTimeFormat` (en-US)
* `Intl.ListFormat` (en-US)
* `Intl.NumberFormat` (en-US)
* `Intl.PluralRules` (en-US)
* `Intl.RelativeTimeFormat` (en-US)
* `Intl.Locale` (en-US)
### WebAssembly

* `WebAssembly` (en-US)
* `WebAssembly.Module` (en-US)
* `WebAssembly.Instance` (en-US)
* `WebAssembly.Memory` (en-US)
* `WebAssembly.Table` (en-US)
* `WebAssembly.CompileError` (en-US)
* `WebAssembly.LinkError` (en-US)
* `WebAssembly.RuntimeError` (en-US)
敘述句
---

本章節記錄了所有 JavaScript 敘述句與宣告 (en-US)。

### 流程控制

* `Block`
* `break`
* `continue`
* `Empty` (en-US)
* `if...else`
* `switch`
* `throw` (en-US)
* `try...catch`
### 宣告

* `var`
* `let`
* `const`
### 函數與類別

* `function` (en-US)
* `function*`
* `async function`
* `return`
* `class` (en-US)
### 迭代

* `do...while`
* `for`
* `for each...in`
* `for...in`
* `for...of` (en-US)
* `for await...of` (en-US)
* `while`
### Other

* `debugger`
* `import`
* `label`
* `with` (en-US)
表示法與運算子
-------

本章節記錄了所有 JavaScript 表示法與運算子。

### 主要運算式

* `this`
* `function` (en-US)
* `class` (en-US)
* `function*` (en-US)
* `yield` (en-US)
* `yield*` (en-US)
* `async function` (en-US)
* `await`
* `[]`
* `{}` (en-US)
* `/ab+c/i` (en-US)
* `( )` (en-US)
* `null` (en-US)
### 左手邊運算式

* Property accessors (en-US)
* `new`
* `new.target` (en-US)
* `super`
* `...obj` (en-US)
### 遞增與遞減

* `A++` (en-US)
* `A--` (en-US)
* `++A` (en-US)
* `--A` (en-US)
### 一元運算子

* `delete`
* `void` (en-US)
* `typeof`
* `+` (en-US)
* `-` (en-US)
* `~` (en-US)
* `!` (en-US)
### 算術運算子

* `+` (en-US)
* `-` (en-US)
* `/` (en-US)
* `*` (en-US)
* `%` (en-US)
* `**` (en-US)
### 關係運算子

* `in` (en-US)
* `instanceof` (en-US)
* `<` (en-US)
* `>` (en-US)
* `<=` (en-US)
* `>=` (en-US)
### 相等運算子

* `==` (en-US)
* `!=` (en-US)
* `===` (en-US)
* `!==` (en-US)
### 位元移位運算子

* `<<` (en-US)
* `>>` (en-US)
* `>>>` (en-US)
### 二元位元運算子

* `&` (en-US)
* `|` (en-US)
* `^` (en-US)
### 二元邏輯運算子

* `&&` (en-US)
* `||` (en-US)
### 條件(三元)運算子

* `(condition ? ifTrue : ifFalse)`
### 賦值運算子

* `=` (en-US)
* `*=` (en-US)
* `/=` (en-US)
* `%=` (en-US)
* `+=` (en-US)
* `-=` (en-US)
* `<<=` (en-US)
* `>>=` (en-US)
* `>>>=` (en-US)
* `&=` (en-US)
* `^=` (en-US)
* `|=` (en-US)
* `[a, b] = [1, 2]`
* `{a, b} = {a:1, b:2}`
函數
--

本章節說明如何使用 JavaScript 函數 (en-US) 來開發你的應用程式。

* `arguments` (en-US)
* Arrow functions
* Default parameters
* Rest parameters
其他參考頁面
------

* Lexical grammar
* Data types and data structures
* Strict mode
* Deprecated features (en-US)


並行模型和事件循環 - JavaScript

並行模型和事件循環
=========

JavaScript 的並行模型（concurrency model）是基於「事件循環（event loop）」，其在運作上跟 C 或是 Java 有很大的不同。

執行環境概念（Runtime concepts）
------------------------

下面的內容解釋了一個理論模型，現代 JavaScript 引擎實作了及很大程度地最佳化了該圖所描述的語意。

### 視覺化呈現（Visual representation）

![Stack, heap, queue](/zh-TW/docs/Web/JavaScript/Event_loop/the_javascript_runtime_environment_example.svg)

### 堆疊（Stack）

呼叫函式（Function）會形成一個 *frame* 的堆疊。

```js
function foo(b) {
  var a = 10;
  return a + b + 11;
}

function bar(x) {
  var y = 3;
  return foo(x \* y);
}

console.log(bar(7));
```

當呼叫 `bar` 時，會產生一個含有 `bar` 的參數及區域變數的 frame，而在 `bar` 呼叫了 `foo` 時，含有 `foo` 參數及變數的第二個 frame 就會被置於堆疊的最上面。當 `foo` 回傳後，最上面的 frame 會被抽離堆疊（僅留下 `bar` 的呼叫 frame）。然後當 bar 返回之後，堆疊就會清空。

### 堆積（Heap）

物件被分配在一個堆積中，一個只表示記憶體中的一個無結構的大區域。

### 佇列（Queue）

JavaScript 執行環境包含一個訊息佇列，裡面是待處理的訊息，其中每個訊息都與一個 function 相關聯。當堆疊中有足夠空間時，會從訊息佇列拿取一個訊息進行處理，處理過程包含了呼叫相關聯的 function。只有當堆疊清空時，該訊息才算是完成處理。

事件循環（Event loop）
----------------

之所以被稱為事件循環，是因為經常被以如下的方式實作：

```js
while (queue.waitForMessage()) {
  queue.processNextMessage();
}
```

當沒有任何訊息時，`queue.waitForMessage` 會同步地等待新訊息到來。

### 執行到完成（Run-to-completion）

每一個訊息處理完成之後才會執行下一個。當分析你的程式的時候，上述提供了優秀的特性，像是當一個函式開始執行時，他不會被取代且其他程式碼執行前先完成（而且可以修改這個函式操作的資料）。這特性與 C 不同，在 C 當中，當一個函式在執行緒中執行時，隨時可以被其他執行緒中的程式碼中止。

這模型的缺點是：若是一個訊息要執行很久才完成，網頁應用程式會無法執行一些使用者的基本操作，如點擊按鈕或是捲動頁面。瀏覽器為了要緩解這問題，會跳出視窗「該動作回應時間過久（a script taking too long to run）」。良好的實作方式是縮短執行訊息，若可能的話，將一個訊息切成數個訊息執行。

### 添加訊息（Adding message）

瀏覽器中，會添加訊息是由於事件的觸動，以及伴隨著事件的監聽者。若是沒有事件監聽者，則該事件的觸動就不會形成訊息，例如說一個點擊的動作伴隨著點擊事件監聽者就會形成一個新的訊息，其他類事件亦然。

呼叫 `setTimeout` (en-US) 時有兩個參數：第一個是會被加入到佇列中的訊息，第二個參數為延遲時間（預設為`0`）。若無其他訊息在佇列中，則這個訊息會在設定的延遲後立刻被處理。但若佇列內有其他訊息，`setTimeout` 的訊息必須等到其他訊息處理完。因此第二個時間參數只能表示為最少時間，而不是一個精準的時間。

這裡有個示範此概念的例子（`setTimeout`在其計時器到期後不會立刻執行）：

```js
const s = new Date().getSeconds();

setTimeout(function () {
  // prints out "2", meaning that the callback is not called immediately after 500 milliseconds.
  console.log("Ran after " + (new Date().getSeconds() - s) + " seconds");
}, 500);

while (true) {
  if (new Date().getSeconds() - s >= 2) {
    console.log("Good, looped for 2 seconds");
    break;
  }
}
```

### 零延遲（Zero delay）

 「零延遲」並非意味著回呼函式（callback function）會在 0 毫秒之後立刻執行。當使用延遲 0 毫秒參數來呼叫 `setTimeout` (en-US) 函式並非是程式會過了該段時間就會執行，而是會參考佇列中等待的訊息數量。
 在下面範例中，「this is just a message」會寫在 setTimeout 的回呼訊息被執行之前，因為該時間段參數是要求執行環境處理所需的最少等待時間，而非一個保證時間。

```js
(function () {
  console.log("this is the start");

  setTimeout(function cb() {
    console.log("this is a msg from call back");
  });

  console.log("this is just a message");

  setTimeout(function cb1() {
    console.log("this is a msg from call back1");
  }, 0);

  console.log("this is the end");
})();

// "this is the start"
// "this is just a message"
// "this is the end"
// "this is a msg from call back"
// "this is a msg from call back1"
```

### 多個執行環境的互相溝通（Several Runtime communicating together）

Web worker 或是跨來源網域（cross-origin）的 `iframe` 都會有各自的堆疊、堆積及訊息佇列。兩個特定的執行環境只能透過 `postMessage` (en-US) 這個方法來溝通。如果一個執行環境有監聽 `message` 事件時，另一個執行環境便可透過這個方法來新增一個訊息到該執行環境中。

絕不阻塞（Never blocking）
--------------------

事件循環這個模型有一個非常有趣的特色就是永不阻塞，這與其他語言不一樣。I/O 的處理通常會經由事件以及回呼函式實作，因此當一個程式正在等待 IndexedDB 的查詢結果或是回傳 XHR 請求時，依舊可以執行其他像是使用者輸入的動作。

例外（exceptions）永遠存在，像是 `alert` 或是同步的 XHR，但好的實作方式就是避開他們。另外要注意個是，例外的例外一直是存在的（但通常為實作時的錯誤而非其他情況）。


Strict mode - JavaScript

Strict mode
===========

ECMAScript 5 提供開發者語法嚴格、語法受限的模式 (strict mode) ，會影響語法的使用但沒支援受限模式的瀏覽器一樣可以跑，只是行為有很大的可能會跟你想的不一樣。所以別太依賴受限模式，除非你做過功能性測試。另外這個模式可以混用在普通模式裡，你可以利用這個特性慢慢把舊的程式碼轉變成完全嚴謹和低變化性的狀態。

這個模式裡做了些語意上的修正:

1. 透過拋出錯誤的方式消除一些安靜的錯誤（意指不再靜默地忽略某些錯誤）
2. 修正會阻礙 JavaScript 引擎進行最佳化的錯誤: 相同的程式碼在嚴格模式有時候能運行得比非嚴格模式來的快
3. 禁止使用一些有可能被未來版本 ECMAScript 定義的語法

參考 過渡到嚴格模式 (en-US)，如果你希望將你的程式碼在 JavaScript 語法嚴格、語法受限下執行。

**備註：** Sometimes, you'll see the default, non-strict, mode referred to as "sloppy mode". This isn't an official term, but be aware of it, just in case.

用法
--

嚴格模式可以用於整份腳本或個別函數中。不要在封閉的大括弧內 `{}` 這樣做； 這麼做在上下文中是沒有效果的。`eval` 程式、`Function`、事件處理參數、傳入 `WindowTimers.setTimeout()` (en-US) 函數的字串都是整個腳本，開啟嚴格模式他也會如預期般運作。

### Strict mode for scripts

To invoke strict mode for an entire script, put the *exact* statement `"use strict";` (or `'use strict';`) before any other statements.

```js
// Whole-script strict mode syntax
"use strict";
var v = "Hi! I'm a strict mode script!";
```

This syntax has a trap that has already bitten a major site: it isn't possible to blindly concatenate non-conflicting scripts. Consider concatenating a strict mode script with a non-strict mode script: the entire concatenation looks strict! The inverse is also true: non-strict plus strict looks non-strict. Concatenation of strict mode scripts with each other is fine, and concatenation of non-strict mode scripts is fine. Only concatenating strict and non-strict scripts is problematic. It is thus recommended that you enable strict mode on a function-by-function basis (at least during the transition period).

You can also take the approach of wrapping the entire contents of a script in a function and having that outer function use strict mode. This eliminates the concatenation problem but it means that you have to explicitly export any global variables out of the function scope.

### Strict mode for functions

Likewise, to invoke strict mode for a function, put the *exact* statement `"use strict";` (or `'use strict';`) in the function's body before any other statements.

```js
function strict() {
  // Function-level strict mode syntax
  "use strict";
  function nested() {
    return "And so am I!";
  }
  return "Hi! I'm a strict mode function! " + nested();
}
function notStrict() {
  return "I'm not strict.";
}
```

Changes in strict mode
----------------------

Strict mode changes both syntax and runtime behavior. Changes generally fall into these categories: changes converting mistakes into errors (as syntax errors or at runtime), changes simplifying how the particular variable for a given use of a name is computed, changes simplifying `eval` and `arguments`, changes making it easier to write "secure" JavaScript, and changes anticipating future ECMAScript evolution.

### Converting mistakes into errors

Strict mode changes some previously-accepted mistakes into errors. JavaScript was designed to be easy for novice developers, and sometimes it gives operations which should be errors non-error semantics. Sometimes this fixes the immediate problem, but sometimes this creates worse problems in the future. Strict mode treats these mistakes as errors so that they're discovered and promptly fixed.

First, strict mode makes it impossible to accidentally create global variables. In normal JavaScript mistyping a variable in an assignment creates a new property on the global object and continues to "work" (although future failure is possible: likely, in modern JavaScript). Assignments which would accidentally create global variables instead throw in strict mode:

```js
"use strict";
// Assuming a global variable mistypedVariable exists
mistypeVariable = 17; // this line throws a ReferenceError due to the
// misspelling of variable
```

Second, strict mode makes assignments which would otherwise silently fail to throw an exception. For example, `NaN` is a non-writable global variable. In normal code assigning to `NaN` does nothing; the developer receives no failure feedback. In strict mode assigning to `NaN` throws an exception. Any assignment that silently fails in normal code (assignment to a non-writable global or property, assignment to a getter-only property, assignment to a new property on a non-extensible object) will throw in strict mode:

```js
"use strict";

// Assignment to a non-writable global
var undefined = 5; // throws a TypeError
var Infinity = 5; // throws a TypeError

// Assignment to a non-writable property
var obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9; // throws a TypeError

// Assignment to a getter-only property
var obj2 = {
  get x() {
    return 17;
  },
};
obj2.x = 5; // throws a TypeError

// Assignment to a new property on a non-extensible object
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // throws a TypeError
```

Third, strict mode makes attempts to delete undeletable properties throw (where before the attempt would simply have no effect):

```js
"use strict";
delete Object.prototype; // throws a TypeError
```

Fourth, strict mode prior to Gecko 34 requires that all properties named in an object literal be unique. Normal code may duplicate property names, with the last one determining the property's value. But since only the last one does anything, the duplication is simply a vector for bugs, if the code is modified to change the property value other than by changing the last instance. Duplicate property names are a syntax error in strict mode:

**備註：** This is no longer the case in ECMAScript 2015 (Firefox bug 1041128).

```js
"use strict";
var o = { p: 1, p: 2 }; // !!! syntax error
```

Fifth, strict mode requires that function parameter names be unique. In normal code the last duplicated argument hides previous identically-named arguments. Those previous arguments remain available through `arguments[i]`, so they're not completely inaccessible. Still, this hiding makes little sense and is probably undesirable (it might hide a typo, for example), so in strict mode duplicate argument names are a syntax error:

```js
function sum(a, a, c) {
  // !!! syntax error
  "use strict";
  return a + b + c; // wrong if this code ran
}
```

Sixth, strict mode in ECMAScript 5 forbids octal syntax. Octal syntax isn't part of ECMAScript 5, but it's supported in all browsers by prefixing the octal number with a zero: `0644 === 420` and `"\045" === "%"`. In ECMAScript 2015 Octal number is supported by prefixing a number with "`0`o". i.e.

```js
var a = 0o10; // ES2015: Octal
```

Novice developers sometimes believe a leading zero prefix has no semantic meaning, so they use it as an alignment device — but this changes the number's meaning! The leading zero syntax for octals is rarely useful and can be mistakenly used, so strict mode makes it a syntax error:

```js
"use strict";
var sum =
  015 + // !!! syntax error
  197 +
  142;

var sumWithOctal = 0o10 + 8;
console.log(sumWithOctal); // 16
```

Seventh, strict mode in ECMAScript 2015 forbids setting properties on primitive (en-US) values. Without strict mode, setting properties is simply ignored (no-op), with strict mode, however, a `TypeError` (en-US) is thrown.

```js
(function () {
  "use strict";

  false.true = ""; // TypeError
  (14).sailing = "home"; // TypeError
  "with".you = "far away"; // TypeError
})();
```

### Simplifying variable uses

Strict mode simplifies how variable names map to particular variable definitions in the code. Many compiler optimizations rely on the ability to say that variable *X* is stored in *that* location: this is critical to fully optimizing JavaScript code. JavaScript sometimes makes this basic mapping of name to variable definition in the code impossible to perform until runtime. Strict mode removes most cases where this happens, so the compiler can better optimize strict mode code.

First, strict mode prohibits `with`. The problem with `with` is that any name inside the block might map either to a property of the object passed to it, or to a variable in surrounding (or even global) scope, at runtime: it's impossible to know which beforehand. Strict mode makes `with` a syntax error, so there's no chance for a name in a `with` to refer to an unknown location at runtime:

```js
"use strict";
var x = 17;
with (obj) {
  // !!! syntax error
  // If this weren't strict mode, would this be var x, or
  // would it instead be obj.x? It's impossible in general
  // to say without running the code, so the name can't be
  // optimized.
  x;
}
```

The simple alternative of assigning the object to a short name variable, then accessing the corresponding property on that variable, stands ready to replace `with`.

Second, `eval` of strict mode code does not introduce new variables into the surrounding scope. In normal code `eval("var x;")` introduces a variable `x` into the surrounding function or the global scope. This means that, in general, in a function containing a call to `eval` every name not referring to an argument or local variable must be mapped to a particular definition at runtime (because that `eval` might have introduced a new variable that would hide the outer variable). In strict mode `eval` creates variables only for the code being evaluated, so `eval` can't affect whether a name refers to an outer variable or some local variable:

```js
var x = 17;
var evalX = eval("'use strict'; var x = 42; x;");
console.assert(x === 17);
console.assert(evalX === 42);
```

Relatedly, if the function `eval` is invoked by an expression of the form `eval(...)` in strict mode code, the code will be evaluated as strict mode code. The code may explicitly invoke strict mode, but it's unnecessary to do so.

```js
function strict1(str) {
  "use strict";
  return eval(str); // str will be treated as strict mode code
}
function strict2(f, str) {
  "use strict";
  return f(str); // not eval(...): str is strict if and only
  // if it invokes strict mode
}
function nonstrict(str) {
  return eval(str); // str is strict if and only
  // if it invokes strict mode
}

strict1("'Strict mode code!'");
strict1("'use strict'; 'Strict mode code!'");
strict2(eval, "'Non-strict code.'");
strict2(eval, "'use strict'; 'Strict mode code!'");
nonstrict("'Non-strict code.'");
nonstrict("'use strict'; 'Strict mode code!'");
```

Thus names in strict mode `eval` code behave identically to names in strict mode code not being evaluated as the result of `eval`.

Third, strict mode forbids deleting plain names. `delete name` in strict mode is a syntax error:

```js
"use strict";

var x;
delete x; // !!! syntax error

eval("var y; delete y;"); // !!! syntax error
```

### Making `eval` and `arguments` simpler

Strict mode makes `arguments` and `eval` less bizarrely magical. Both involve a considerable amount of magical behavior in normal code: `eval` to add or remove bindings and to change binding values, and `arguments` by its indexed properties aliasing named arguments. Strict mode makes great strides toward treating `eval` and `arguments` as keywords, although full fixes will not come until a future edition of ECMAScript.

First, the names `eval` and `arguments` can't be bound or assigned in language syntax. All these attempts to do so are syntax errors:

```js
"use strict";
eval = 17;
arguments++;
++eval;
var obj = { set p(arguments) {} };
var eval;
try {
} catch (arguments) {}
function x(eval) {}
function arguments() {}
var y = function eval() {};
var f = new Function("arguments", "'use strict'; return 17;");
```

Second, strict mode code doesn't alias properties of `arguments` objects created within it. In normal code within a function whose first argument is `arg`, setting `arg` also sets `arguments[0]`, and vice versa (unless no arguments were provided or `arguments[0]` is deleted). `arguments` objects for strict mode functions store the original arguments when the function was invoked. `arguments[i]` does not track the value of the corresponding named argument, nor does a named argument track the value in the corresponding `arguments[i]`.

```js
function f(a) {
  "use strict";
  a = 42;
  return [a, arguments[0]];
}
var pair = f(17);
console.assert(pair[0] === 42);
console.assert(pair[1] === 17);
```

Third, `arguments.callee` is no longer supported. In normal code `arguments.callee` refers to the enclosing function. This use case is weak: simply name the enclosing function! Moreover, `arguments.callee` substantially hinders optimizations like inlining functions, because it must be made possible to provide a reference to the un-inlined function if `arguments.callee` is accessed. `arguments.callee` for strict mode functions is a non-deletable property which throws when set or retrieved:

```js
"use strict";
var f = function () {
  return arguments.callee;
};
f(); // throws a TypeError
```

### "Securing" JavaScript

Strict mode makes it easier to write "secure" JavaScript. Some websites now provide ways for users to write JavaScript which will be run by the website *on behalf of other users*. JavaScript in browsers can access the user's private information, so such JavaScript must be partially transformed before it is run, to censor access to forbidden functionality. JavaScript's flexibility makes it effectively impossible to do this without many runtime checks. Certain language functions are so pervasive that performing runtime checks has considerable performance cost. A few strict mode tweaks, plus requiring that user-submitted JavaScript be strict mode code and that it be invoked in a certain manner, substantially reduce the need for those runtime checks.

First, the value passed as `this` to a function in strict mode is not forced into being an object (a.k.a. "boxed"). For a normal function, `this` is always an object: either the provided object if called with an object-valued `this`; the value, boxed, if called with a Boolean, string, or number `this`; or the global object if called with an `undefined` or `null` `this`. (Use `call`, `apply`, or `bind` to specify a particular `this`.) Not only is automatic boxing a performance cost, but exposing the global object in browsers is a security hazard, because the global object provides access to functionality that "secure" JavaScript environments must restrict. Thus for a strict mode function, the specified `this` is not boxed into an object, and if unspecified, `this` will be `undefined`:

```js
"use strict";
function fun() {
  return this;
}
console.assert(fun() === undefined);
console.assert(fun.call(2) === 2);
console.assert(fun.apply(null) === null);
console.assert(fun.call(undefined) === undefined);
console.assert(fun.bind(true)() === true);
```

That means, among other things, that in browsers it's no longer possible to reference the `window` object through `this` inside a strict mode function.

Second, in strict mode it's no longer possible to "walk" the JavaScript stack via commonly-implemented extensions to ECMAScript. In normal code with these extensions, when a function `fun` is in the middle of being called, `fun.caller` is the function that most recently called `fun`, and `fun.arguments` is the `arguments` for that invocation of `fun`. Both extensions are problematic for "secure" JavaScript, because they allow "secured" code to access "privileged" functions and their (potentially unsecured) arguments. If `fun` is in strict mode, both `fun.caller` and `fun.arguments` are non-deletable properties which throw when set or retrieved:

```js
function restricted() {
  "use strict";
  restricted.caller; // throws a TypeError
  restricted.arguments; // throws a TypeError
}
function privilegedInvoker() {
  return restricted();
}
privilegedInvoker();
```

Third, `arguments` for strict mode functions no longer provide access to the corresponding function call's variables. In some old ECMAScript implementations `arguments.caller` was an object whose properties aliased variables in that function. This is a security hazard because it breaks the ability to hide privileged values via function abstraction; it also precludes most optimizations. For these reasons no recent browsers implement it. Yet because of its historical functionality, `arguments.caller` for a strict mode function is also a non-deletable property which throws when set or retrieved:

```js
"use strict";
function fun(a, b) {
  "use strict";
  var v = 12;
  return arguments.caller; // throws a TypeError
}
fun(1, 2); // doesn't expose v (or a or b)
```

### Paving the way for future ECMAScript versions

Future ECMAScript versions will likely introduce new syntax, and strict mode in ECMAScript 5 applies some restrictions to ease the transition. It will be easier to make some changes if the foundations of those changes are prohibited in strict mode.

First, in strict mode a short list of identifiers become reserved keywords. These words are `implements`, `interface`, `let`, `package`, `private`, `protected`, `public`, `static`, and `yield`. In strict mode, then, you can't name or use variables or arguments with these names.

```js
function package(protected) {
  // !!!
  "use strict";
  var implements; // !!!

  // !!!
  interface: while (true) {
    break interface; // !!!
  }

  function private() {} // !!!
}
function fun(static) {
  "use strict";
} // !!!
```

Two Mozilla-specific caveats: First, if your code is JavaScript 1.7 or greater (for example in chrome code or when using the right `<script type="">`) and is strict mode code, `let` and `yield` have the functionality they've had since those keywords were first introduced. But strict mode code on the web, loaded with `<script src="">` or `<script>...</script>`, won't be able to use `let`/`yield` as identifiers. Second, while ES5 unconditionally reserves the words `class`, `enum`, `export`, `extends`, `import`, and `super`, before Firefox 5 Mozilla reserved them only in strict mode.

Second, strict mode prohibits function statements not at the top level of a script or function. In normal code in browsers, function statements are permitted "everywhere". *This is not part of ES5 (or even ES3)!* It's an extension with incompatible semantics in different browsers. Future ECMAScript editions will hopefully specify new semantics for function statements not at the top level of a script or function. Prohibiting such function statements in strict mode "clears the deck" for specification in a future ECMAScript release:

```js
"use strict";
if (true) {
  function f() {} // !!! syntax error
  f();
}

for (var i = 0; i < 5; i++) {
  function f2() {} // !!! syntax error
  f2();
}

function baz() {
  // kosher
  function eit() {} // also kosher
}
```

This prohibition isn't strict mode proper, because such function statements are an extension of basic ES5. But it is the recommendation of the ECMAScript committee, and browsers will implement it.

Strict mode in browsers
-----------------------

The major browsers now implement strict mode. However, don't blindly depend on it since there still are numerous Browser versions used in the wild that only have partial support for strict mode or do not support it at all (e.g. Internet Explorer below version 10!). *Strict mode changes semantics.* Relying on those changes will cause mistakes and errors in browsers which don't implement strict mode. Exercise caution in using strict mode, and back up reliance on strict mode with feature tests that check whether relevant parts of strict mode are implemented. Finally, make sure to *test your code in browsers that do and don't support strict mode*. If you test only in browsers that don't support strict mode, you're very likely to have problems in browsers that do, and vice versa.

See also
--------

* Where's Walden? » New ES5 strict mode support: now with poison pills!
* Where's Walden? » New ES5 strict mode requirement: function statements not at top level of a program or function are prohibited
* Where's Walden? » New ES5 strict mode support: new vars created by strict mode eval code are local to that code only
* JavaScript "use strict" tutorial for beginners.
* John Resig - ECMAScript 5 Strict Mode, JSON, and More
* ECMA-262-5 in detail. Chapter 2. Strict Mode.
* Strict mode compatibility table
* Transitioning to strict mode (en-US)


迭代協議 - JavaScript

迭代協議
====

為 ECMAScript 2015 中的一些補充內容，並非新的內建物件或語法，而是協議。這些協議可被任何遵守特定協定的物件所實作。

本文介紹兩種協議：可迭代協議（iterable protocol）以及迭代器協議（iterator protocol）。

可迭代協議
-----

\*\*可迭代（iterable）\*\*協議允許 JavaScript 物件定義或客制他們的迭代行為，例如哪些值可在 `for..of` (en-US) 語法結構中被迭代出來。部分內建型別為擁有預設迭代行為的可迭代內建物件（built-in iterables），如 `Array` 或 `Map`，而其他型別（如 `Object` (en-US)）則否。

為了成為**可迭代的（iterable）**，一個物件必須實作 **@@iterator** 方法，意思是這個物件（或其原型鏈 (en-US)中的其中一個原型物件）必須擁有一個鍵（key）值為 **@@iterator**（即 `Symbol.iterator` (en-US) 常數）的屬性：

| 屬性 | 值 |
| --- | --- |
| `[Symbol.iterator]` | 回傳符合迭代器協議（iterator protocol）之物件的無引數函式。 |

每當物件需要被迭代時（比如在一個開始的 `for..of` 迴圈中），物件的 `@@iterator` 方法會被以不傳入引數的方式呼叫，並會使用其回傳的\*\*迭代器（iterator）\*\*來獲得被迭代出來的值。

迭代器協議
-----

\*\*迭代器（iterator）\*\*協議定義了一個標準方式來產出一連串（有限或無限）的值，並且可能於所有值都被產出後回傳一個值。

當物件以下列語義實作了 **`next()`** 方法即為一個迭代器：

| 屬性 | 值 |
| --- | --- |
| `next` | 回傳一個至少擁有以下兩個屬性之物件的無引數函式：* `done`（布林值）
    + 若迭代器已迭代完畢整個可迭代序列，則值為
     `true`。在這個情況下
     `value` 可以是代表迭代器的*回傳值*。
    + 若迭代器能夠產出序列中的下一個值，則值為
     `false`。相當於完全不指定 `done` 屬性。
* `value` - 任何由迭代器所回傳的 JavaScript 值。可於
 `done` 為 `true` 時省略。

`next` 方法必須總是回傳一個包含符合 `done` 及
 `value` 屬性的物件。假如回傳了一個非物件值（如
 `false` 或 `undefined`），則將會拋出一個
 `TypeError` (en-US) 錯誤。
  |

**備註：** 我們無法反射性的一眼看出一個特定的物件是否實作了迭代器協議，然而要建立一個同時滿足迭代器及可迭代協議的物件卻是相當容易（如下例所示）。範例的做法允許一個迭代器被各個預期其可迭代行為的語法所消費。因此很少有需要實作迭代器協議而沒有實作可迭代協議的情況。

```js
var myIterator = {
  next: function () {
    // ...
  },
  [Symbol.iterator]: function () {
    return this;
  },
};
```

迭代協議使用範例
--------

`String` 為一個可迭代內建物件（built-in iterable object）的範例：

```js
var someString = "hi";
typeof someString[Symbol.iterator]; // "function"
```

`String` 的預設迭代器 (en-US)會回傳字串中的一個一個字元：

```js
var iterator = someString[Symbol.iterator]();
iterator + ""; // "[object String Iterator]"

iterator.next(); // { value: "h", done: false }
iterator.next(); // { value: "i", done: false }
iterator.next(); // { value: undefined, done: true }
```

部分內建語法結構（built-in constructs），如 spread syntax (en-US)，其內部也使用了相同的迭代協議：

```js
[...someString]; // ["h", "i"]
```

我們可以藉由提供我們自己的 `@@iterator` 來重新定義迭代行為：

```js
var someString = new String("hi"); // need to construct a String object explicitly to avoid auto-boxing

someString[Symbol.iterator] = function () {
  return {
    // this is the iterator object, returning a single element, the string "bye"
    next: function () {
      if (this._first) {
        this._first = false;
        return { value: "bye", done: false };
      } else {
        return { done: true };
      }
    },
    \_first: true,
  };
};
```

請注意，重新定義 `@@iterator` 會影響使用迭代協議之內建語法結構的行為：

```js
[...someString]; // ["bye"]
someString + ""; // "hi"
```

可迭代範例
-----

### 可迭代內建物件

`String`、`Array`、`TypedArray` (en-US)、`Map` 以及 `Set` 全都是可迭代內建物件，因為他們每一個的原型物件皆實作了 `@@iterator` 方法。

### 自定義可迭代物件

我們可以建立自己的可迭代物件，像是：

```js
var myIterable = {};
myIterable[Symbol.iterator] = function\* () {
  yield 1;
  yield 2;
  yield 3;
};
[...myIterable]; // [1, 2, 3]
```

### 接受可迭代物件的內建 API

有許多 APIs 接受可迭代物件，如：`Map([iterable])`、`WeakMap([iterable])` (en-US)、`Set([iterable])` 及 `WeakSet([iterable])` (en-US)：

```js
var myObj = {};
new Map([
  [1, "a"],
  [2, "b"],
  [3, "c"],
]).get(2); // "b"
new WeakMap([
  [{}, "a"],
  [myObj, "b"],
  [{}, "c"],
]).get(myObj); // "b"
new Set([1, 2, 3]).has(3); // true
new Set("123").has("2"); // true
new WeakSet(
  (function\* () {
    yield {};
    yield myObj;
    yield {};
  })(),
).has(myObj); // true
```

另外可參考 `Promise.all(iterable)`、`Promise.race(iterable)` 以及 `Array.from()`。

### 用於可迭代物件的語法

部分陳述式（statements）及運算式（expressions）為預期用於可迭代物件，例如 `for-of` (en-US) 迴圈、spread syntax (en-US)、`yield*` (en-US)，及解構賦值：

```js
for (let value of ["a", "b", "c"]) {
  console.log(value);
}
// "a"
// "b"
// "c"

[..."abc"]; // ["a", "b", "c"]

function\* gen() {
  yield\* ["a", "b", "c"];
}

gen().next(); // { value:"a", done:false }

[a, b, c] = new Set(["a", "b", "c"]);
a; // "a"
```

### 非良好的（Non-well-formed）可迭代物件

假如可迭件物件的 `@@iterator` 方法不是回傳一個迭代器物件，即是非良好的（non-well-formed）可迭代物件。如以下方式使用可能會導致執行時期異常或錯誤行為：

```js
var nonWellFormedIterable = {}
nonWellFormedIterable[Symbol.iterator] = () => 1
[...nonWellFormedIterable] // TypeError: [] is not a function
```

迭代器範例
-----

### 簡單的迭代器

```js
function makeIterator(array) {
  var nextIndex = 0;

  return {
    next: function () {
      return nextIndex < array.length
        ? { value: array[nextIndex++], done: false }
        : { done: true };
    },
  };
}

var it = makeIterator(["yo", "ya"]);

console.log(it.next().value); // 'yo'
console.log(it.next().value); // 'ya'
console.log(it.next().done); // true
```

### 無限迭代器

```js
function idMaker() {
  var index = 0;

  return {
    next: function () {
      return { value: index++, done: false };
    },
  };
}

var it = idMaker();

console.log(it.next().value); // '0'
console.log(it.next().value); // '1'
console.log(it.next().value); // '2'
// ...
```

### 搭配生成器（generator）

```js
function\* makeSimpleGenerator(array) {
  var nextIndex = 0;

  while (nextIndex < array.length) {
    yield array[nextIndex++];
  }
}

var gen = makeSimpleGenerator(["yo", "ya"]);

console.log(gen.next().value); // 'yo'
console.log(gen.next().value); // 'ya'
console.log(gen.next().done); // true

function\* idMaker() {
  var index = 0;
  while (true) yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // '0'
console.log(gen.next().value); // '1'
console.log(gen.next().value); // '2'
// ...
```

### 搭配 ES2015 類別

```js
class SimpleClass {
  constructor(data) {
    this.index = 0;
    this.data = data;
  }

  [Symbol.iterator]() {
    return {
      next: () => {
        if (this.index < this.data.length) {
          return { value: this.data[this.index++], done: false };
        } else {
          this.index = 0; //If we would like to iterate over this again without forcing manual update of the index
          return { done: true };
        }
      },
    };
  }
}

const simple = new SimpleClass([1, 2, 3, 4, 5]);

for (const val of simple) {
  console.log(val); //'0' '1' '2' '3' '4' '5'
}
```

生成器物件是迭代器還是可迭代物件？
-----------------

生成器物件（generator object） (en-US)同時為迭代器及可迭代物件：

```js
var aGeneratorObject = (function\* () {
  yield 1;
  yield 2;
  yield 3;
})();
typeof aGeneratorObject.next;
// "function", because it has a next method, so it's an iterator
typeof aGeneratorObject[Symbol.iterator];
// "function", because it has an @@iterator method, so it's an iterable
aGeneratorObject[Symbol.iterator]() === aGeneratorObject;
// true, because its @@iterator method returns itself (an iterator), so it's an well-formed iterable
[...aGeneratorObject];
// [1, 2, 3]
```

參見
--

* 更多關於 ES2015 生成器（generators）的資訊，可參考生成器函式 function\* 文件。


樣板字面值 - JavaScript

樣板字面值
=====

樣板字面值（Template literals）是允許嵌入運算式的字串字面值（string literals）。你可以透過樣板字面值來使用多行字串及字串內插（string interpolation）功能。他們在 ES2015 規範的先行版本中被稱為「樣板字串（template strings）」。

語法
--
```

`string text`

`string text line 1
 string text line 2`

`string text ${expression} string text`

tag `string text ${expression} string text`
```

描述
--

樣板字面值（Template literals）被反引號（back-tick，重音符號）：` ` 字元封閉，代替了雙或單引號。樣板字面值可以包含由錢字元及花括號所構成（`${expression}`）的佔位符（placeholders）。這個在佔位符中的運算式以及在它們之間的文字會被傳入一個函式。預設函式只是將這些部分組合成一個單一的字串。如果在樣板字面值前有一個運算式（`tag` here），則此樣板字串被稱為「標籤樣板字面值（tagged template literal）」。在此情況下，標籤運算式（通常是一個函式）會被呼叫來處理樣板字面值，讓你可以在函式回傳之前進行操作。要在樣板字面值中跳脫一個反引號，可以於反引號前加上一個反斜線（backslash）**\** 。

```js
`\`` === "`"; // --> true
```

### 多行字串

任何在樣板字面值中使用、插入的換行符號，都是樣板字面值的一部份。在普通的字串中，我們需要使用如下的語法以達到換行的效果：

```js
console.log("string text line 1\n" + "string text line 2");
// "string text line 1
// string text line 2"
```

但使用樣板字面值，你只需要撰寫如下所示的程式碼，就能達到同樣的效果：

```js
console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"
```

### 運算式內插

要在普通的字串中內嵌運算式，我們必須使用如下語法：

```js
var a = 5;
var b = 10;
console.log("Fifteen is " + (a + b) + " and\nnot " + (2 \* a + b) + ".");
// "Fifteen is 15 and
// not 20."
```

現在有了樣板字面值，我們可以用一種更優雅的寫法，讓語法更具可讀性：

```js
var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 \* a + b}.`);
// "Fifteen is 15 and
// not 20."
```

### 巢狀樣板

In certain times, nesting a template is the easiest and perhaps more readable way to have configurable strings. Within a backticked template it is simple to allow inner backticks simply by using them inside a placeholder `${ }` within the template. For instance, if condition a is true: then return this templated literal.

In ES5:

```js
var classes = "header";
classes += isLargeScreen()
  ? ""
  : item.isCollapsed
    ? " icon-expander"
    : " icon-collapser";
```

In ES2015 with template literals and without nesting:

```js
const classes = `header ${
 isLargeScreen() ? "" : item.isCollapsed ? "icon-expander" : "icon-collapser"
}`;
```

In ES2015 with nested template literals:

```js
const classes = `header ${
 isLargeScreen() ? "" : `icon-${item.isCollapsed ? "expander" : "collapser"}`
}`;
```

### 標籤樣板字面值

標籤樣板字面值是一種更高級的樣板字面值形式，允許你透過標籤函數操作樣板字面值的輸出。標籤函數的第一個參數是一字串陣列，其餘參數則是處理過的表達式。最終，你可以返回一個經處理後的字串，甚至是完全不一樣的東西（如下述第二個範例中）。標籤函數的名稱可以是任何你想要的。

```js
var person = "Mike";
var age = 28;

function myTag(strings, personExp, ageExp) {
  var str0 = strings[0]; // "that "
  var str1 = strings[1]; // " is a "

  // There is technically a string after
  // the final expression (in our example),
  // but it is empty (""), so disregard.
  // var str2 = strings[2];

  var ageStr;
  if (ageExp > 99) {
    ageStr = "centenarian";
  } else {
    ageStr = "youngster";
  }

  return str0 + personExp + str1 + ageStr;
}

var output = myTag`that ${person} is a ${age}`;

console.log(output);
// that Mike is a youngster
```

標籤函數不一定要回傳一個字串，如下列範例：

```js
function template(strings, ...keys) {
  return function (...values) {
    var dict = values[values.length - 1] || {};
    var result = [strings[0]];
    keys.forEach(function (key, i) {
      var value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result.join("");
  };
}

var t1Closure = template`${0}${1}${0}!`;
t1Closure("Y", "A"); // "YAY!"
var t2Closure = template`${0} ${"foo"}!`;
t2Closure("Hello", { foo: "World" }); // "Hello World!"
```

### 原始字串

標籤函數的第一個參數，帶有一個特殊的屬性「 `raw` 」，允許你獲取原始輸入的、未處理任何轉義序列的字串值。

```js
function tag(strings) {
  console.log(strings.raw[0]);
}

tag`string text line 1 \n string text line 2`;
// logs "string text line 1 \n string text line 2" ,
// including the two characters '\' and 'n'
```

此外, 使用 `String.raw()` (en-US) 方法建立的原始字串，也與預設的樣板函數和字串串接會建立的字串相同。

```js
var str = String.raw`Hi\n${2 + 3}!`;
// "Hi\n5!"

str.length;
// 6

str.split("").join(",");
// "H,i,\,n,5,!"
```

### 標籤樣板字面值和跳脫序列

在 ES2016 的規範中，標籤樣板字面值遵守下列跳脫序列（escape sequences）規則：

* 萬國碼 (Unicode) 跳脫序列由 "\u" 作為開頭, 例： `\u00A9`
* 萬國碼位 (Unicode code point) 由 "\u{}" 作為開頭, 例： `\u{2F804}`
* 十六進位制碼由 "\x" 作為開頭, 例： `\xA9`
* 十進位制碼由 "\" 作為開頭, 例： \251

這表示像是下述的標籤樣板字面值是有問題的，因為根據 ECMAScript 規範，一個語法分析器會嘗試以萬國碼轉義序列去解析它，然後發現序列有誤：

```js
latex`\unicode`;
// Throws in older ECMAScript versions (ES2016 and earlier)
// SyntaxError: malformed Unicode character escape sequence
```

Tagged template literals should allow the embedding of languages (for example DSLs, or LaTeX), where other escapes sequences are common. The ECMAScript proposal Template Literal Revision (stage 4, to be integrated in the ECMAScript 2018 standard) removes the syntax restriction of ECMAScript escape sequences from tagged template literals.

However, illegal escape sequence must still be represented in the "cooked" representation. They will show up as `undefined` (en-US) element in the "cooked" array:

l be represented in the "cooked" representation. They will show up as `undefined` (en-US) element in the "cooked" array:

```js
function latex(str) {
  return { cooked: str[0], raw: str.raw[0] };
}

latex`\unicode`;

// { cooked: undefined, raw: "\\unicode" }
```

Note that the escape sequence restriction is only dropped from *tagged* template literals and not from *untagged* template literals:

```js
let bad = `bad escape sequence: \unicode`;
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-template-literals |

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

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

參見
--

* `String`
* `String.raw()` (en-US)
* Lexical grammar
* Template-like strings in ES3 compatible syntax
* "ES6 in Depth: Template strings" on hacks.mozilla.org


Lexical grammar - JavaScript

Lexical grammar
===============

此篇介紹 Javascript 的 lexical grammar。ECMAScript 的原始碼從左到右被掃描並被轉換成一系列的輸入元素也就是 token、控制字元、行終止字元、註解或是空白字元。ECMAScript 也定義了一些特定的關鍵字和實體語法還有用來自動插入分號來結束陳述式的規則。

控制字元
----

控制字元是用來控制對文本的解釋，但無法被顯示出來。

| 編碼位置 | 名稱 | 縮寫 | 說明 |
| --- | --- | --- | --- |
| `U+200C` | 零寬不連字 | <ZWNJ> | 放置在兩個字元之間來避免在某些語言中這兩個字元被當成連字 (Wikipedia) |
| `U+200D` | 零寬連字 | <ZWJ> | 放置在兩個通常不會發生連字的字元中間在某些語言 來讓他們成為連字 (Wikipedia) |
| `U+FEFF` | 位元組順序記號 | <BOM> | 出現在腳本的開頭，用來標記此腳本是否為 Unicode 還有文本的位元組順序 (Wikipedia) |

空白字元
----

空白字元提升了程式碼的可讀性也能將 tokens 分開。這些字元通常對程式的執行是不必要的。壓縮源碼工具通常會移除不必要的空白來減少資料傳輸量。

| 編碼位置 | 名稱 | 縮寫 | 說明 | 跳脫字元 |
| --- | --- | --- | --- | --- |
| U+0009 | 定位字元 | <HT> | 橫向定位字元 | \t |
| U+000B | 縱向定位字元 | <VT> | 縱向定位字元 | \v |
| U+000C | 換頁字元 | <FF> | 控制換頁字元 (Wikipedia) | \f |
| U+0020 | 空格 | <SP> | 一般的空白字元 |  |
| U+00A0 | 不中斷空格 | <NBSP> | 一般的空白字元，但禁止自動換行或合併多個空白 (Wikipedia) |  |
| 其他 | 其他 Unicode 空白字元 | <USP> | Wikipedia |  |

行終止字元
-----

除了空白字元之外，行終止字元也用來提升源碼可讀性。然而，在某些情況下行終止字元會影響 Javascript 程式的執行，所以有些地方是被禁止使用的。行終止字元同時也會影響自動插入分號的運作。在正規表達式中，行終止字元屬於 **\s** 的類別。

在 ECMAScript 中，只有以下的 Unicode 碼位被視為行終止字元，其他如 Next Line, NEL, U+0085 等的行終止字元被視為空白字元。

| 編碼位置 | 名稱 | 縮寫 | 說明 | 跳脫字元 |
| --- | --- | --- | --- | --- |
| U+000A | 換行字元 | <LF> | 在 UNIX 類的系統中的換行字元 | \n |
| U+000D | 歸位字元 | <CR> | 在 Commodore 與早期的 Mac 系統中的換行字元 | \r |
| U+2028 | 行分隔字元 | <LS> | Wikipedia |  |
| U+2029 | 段分隔字元 | <PS> | Wikipedia |  |

註解
--

在 Javascript 程式中，註解通常被用來寫提示、註釋、建議或警告。這可以讓程式更好讀也更好理解，同時也是一個很好的除錯工具，可以讓一些程式碼不被執行。

Javascript 有兩種方式寫註解。

第一種是 `//`; 它將在它之後的文本變成註解。例如：

```js
function comment() {
  // 這是一行 Javascript 註解
  console.log("Hello world!");
}
comment();
```

第二種更有彈性的方式是 `/* */` 。

例如，你可以將它用在單行上：

```js
function comment() {
  /\* 這是一行 Javascript 註解 \*/
  console.log("Hello world!");
}
comment();
```

你也可以將它用來寫多行註解：

```js
function comment() {
  /\* 這個註解可以跨越多行。注意只有當我們要結束註解時才寫
 多行註解的終止符號 \*/
  console.log("Hello world!");
}
comment();
```

如果你想要你也可以把它插在一行的中央，雖然它會讓你的程式變得難讀所以請謹慎使用：

```js
function comment(x) {
  console.log("Hello " + x /\* 插入 x 的值 \*/ + " !");
}
comment("world");
```

此外，你也可以把一段程式用註解包起來讓它不被執行：

```js
function comment() {
  /\* console.log('Hello world!'); \*/
}
comment();
```

在這個情況， `console.log()` 永遠不會被呼叫因為它在註解裡面。任意行數的程式碼都可以用這個方法來使之失去作用。

保留字
---

### ECMAScript 2015 保留關鍵字

* `break`
* `case`
* `catch`
* `class` (en-US)
* `const`
* `continue`
* `debugger`
* `default` (en-US)
* `delete`
* `do`
* `else`
* `export`
* `extends` (en-US)
* `finally`
* `for`
* `function` (en-US)
* `if`
* `import`
* `in` (en-US)
* `instanceof` (en-US)
* `new`
* `return`
* `super`
* `switch`
* `this`
* `throw` (en-US)
* `try`
* `typeof`
* `var`
* `void` (en-US)
* `while`
* `with` (en-US)
* `yield` (en-US)
### 未來保留關鍵字

根據 ECMAScript 的規格，以下的關鍵字被保留供未來使用。他們目前沒有功用但未來可能有，所以不能將他們用作識別字。

以下關鍵字將永遠被保留：

* `enum`

以下關鍵字只有在嚴格模式底下才被保留：

* `implements`
* `interface`
* `let`
* `package`
* `private`
* `protected`
* `public`
* `static`

以下關鍵字只有在出現在模組程式碼中時才被保留：

* `await`

#### 舊標準中的未來保留關鍵字

以下關鍵字在舊的 ECMAScript 規格中 (ECMAScript 1 到 3) 為未來保留關鍵：

* `abstract`
* `boolean`
* `byte`
* `char`
* `double`
* `final`
* `float`
* `goto`
* `int`
* `long`
* `native`
* `short`
* `synchronized`
* `throws`
* `transient`
* `volatile`

此外，如 `null`, `true` 與 `false` 等實體語法 (literal) 在 ECMAScript 中不能被用作識別字。

### 保留字的使用

只有當用在識別字的時候保留關鍵字才會被保留 (相對於 `IdentifierNames`) 。如 es5.github.com/#A.1 所述，以下保留關鍵字的用法都屬於`IdentifierNames` 因此是合法的。

```js
a.import
a['import']
a = { import: 'test' }.
```

反之，以下用法不合法因為用在識別字上，識別字屬於 `IdentifierName` 但不包含保留字。識別字用在 `FunctionDeclaration, FunctionExpression, VariableDeclaration` 等等?。而 `IdentifierName` 被用在 `MemberExpression, CallExpression` 等等。

```js
function import() {} // 不合法.
```

實體語法
----

### Null

更多說明請參閱 `null` (en-US) 。

```js
null
```

### 布林值

更多說明請參閱 `Boolean` 。

```js
true
false
```

### 數值

#### 十進制

```js
1234567890
42

// 謹慎使用前導零
0888 // 888 被解析成十進制
0777 // 被解析成八進制, 十進制值為 511
```

數值的實體語法可以可以以零 (`0`) 為首再街上其他十進制數字。然而一但零後面的的數字都小於 8 時，這個數值會被解讀成八進制數字，這個行為不會丟出例外，請參閱 Firefox bug 957513。也請參閱 `parseInt()`。

#### 二進制

二進制數字的語法為一個起首零加上小寫或大小的拉丁字元「B」（`0b` 或 `0B`）。因為這個語法是在 ECMAScript 2015 才新增的，請參閱底下的瀏覽器相容表。如果 `0b` 之後的數字不是 0 或 1，「0b 之後找不到二進制數字」的 `SyntaxError` (en-US) 會被丟出。

```js
0b10000000000000000000000000000000 // 2147483648
0b01111111100000000000000000000000 // 2139095040
0B00000000011111111111111111111111 // 8388607
```

#### 八進制

八進制數字的語法為一個起首零加上小寫或大小的拉丁字元「O」（`0o` 或 `0O`）。因為這個語法是在 ECMAScript 2015 才新增的，請參閱底下的瀏覽器相容表。如果 `0o` 之後的數字不是（01234567）其中之一，「0o 之後找不到八進制數字」的 SyntaxError 會被丟出。

```js
0O755 // 493
0o644 // 420
```

#### 十六進制

十六進制數字的語法為一個起首零加上小寫或大小的拉丁字元"X" (`0x` 或 `0X`)。如果 `0x` 之後的數字不是 (0123456789ABCDEF) 其中之一，"識別字緊接在數值實體語法後"的 SyntaxError 會被丟出。

```js
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
0x123456789ABCDEF   // 81985529216486900
0XA                 // 10
```

### 物件

更多說明請參閱 `Object` (en-US) 及 Object initializer (en-US)。

```js
var o = { a: "foo", b: "bar", c: 42 };

// 簡短表示法 (ES2015 新增)
var a = "foo",
  b = "bar",
  c = 42;
var o = { a, b, c };

// ES2015 以前必須這樣寫
var o = { a: a, b: b, c: c };
```

### 陣列

更多說明請參閱 `Array` 。

```js
[1954, 1974, 1990, 2014]
```

### 字串

```js
'foo'
"bar"
```

#### 十六進制跳脫序列

```js
"\xA9" // "©"
```

#### Unicode 跳脫序列

一個 Unicode 跳脫序列由 `\u` 接上 4 個十六進制的數值所組成。每一個十六進制的數值表示一個 UTF-16 編碼的 2 位元組字元。對於編碼位置在 0~FFFF 之間的字元，其 Unicode 表示法與編碼位置相同。而更高的編碼位置需要兩個跳脫序列來表示，又稱為代理對(surrogate pair)，代理對表示的數值與編碼位置不同 (代理對計算規則 wiki)。

```js
"\u00A9" // "©"
```

#### Unicode 跳脫編碼位置

ECMAScript 2015 新增。使用 Unicode 跳脫編碼位置表示法，即可使用與編碼位置完全相同的表示法 (最高到 `0x10FFFF`) 而不受編碼位置高於 FFFF 需用代理對表示的限制。

更多說明請參閱 `String.fromCodePoint()` (en-US) 或 `String.prototype.codePointAt()` (en-US)。

```js
"\u{2F804}"

// 等價於代理對表示法
"\uD87E\uDC04"
```

### 正規表達式

更多說明請參閱 `RegExp` (en-US) 。

```js
/ab+c/g

// 一個空的正規表示法。
// 兩個斜線之間不得為空，否則將被視為單行註解。
/(?:)/
```

### 範本字串

更多說明請參閱 template strings (en-US) 。

```js
`string text`

`string text line 1
 string text line 2`

`string text ${expression} string text`

tag `string text ${expression} string text`
```

自動插入分號
------

否些 JavaScript statements (en-US) 必須以分號作結，因此會受到自動插入分號 (ASI) 規則影響。

* 空運算式
* `let`, `const`, 變數宣告
* `import`, `export`, 模組宣告
* 運算式
* `debugger`
* `continue`, `break`, `throw`
* `return`

ECMAScript 規格闡明 自動插入分號的三個規則。

1. 如果 行終止字元 或 "}" 出現在不符文法的地方，一個分號會被自動插入在其之前。

```js
{ 1 2 } 3

// 會被 ASI 轉換成

{ 1 2 ;} 3;
```

2. 當一個 token 輸入流到了結尾而解析器仍然無法將其解析為一個完整的程式，一個分號會被自動插入於其後。

在這裡 `++` 並不會被當作作用於變數`b`的 後綴運算元 (en-US)，因為行終止字元出現在`b` 和 `++`之間。

```js
a = b
++c

// 會被 ASI 轉換成

a = b;
++c;
```

3. 當一個運算式中出現 restricted productions 後面接著一個行終止元，一個分號會被自動插入於行終止元之前。以下這些陳述式有"不允許出現行終止元"規則：

* 後綴運算式 (`++` and `--`)
* `continue`
* `break`
* `return`
* `yield`, `yield*`
* `module`

```js
return
a + b

// 會被 ASI 轉換成

return;
a + b;
```

規格
--

| Specification |
| --- |
| ECMAScript Language Specification  |

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

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

參閱
--

* Jeff Walden: Binary and octal numbers
* Mathias Bynens: JavaScript character escape sequences
* `Boolean`
* `Number`
* `RegExp` (en-US)
* `String`


JavaScript 錯誤參考資料 - JavaScript

JavaScript 錯誤參考資料
=================

在這裡，你可以看到一些由 JavaScript 拋出的錯誤一覽。這些錯誤訊息對你的除錯很有幫助，但拋出的錯誤也不是每次都能講清楚。本頁回提供這些錯誤的詳細資訊。所有的錯誤都是由 `Error` (en-US) 物件所建立的物件，有著 `name` 與 `message`。

錯誤會出現在網路主控台、可能還連接到相應頁面，以幫助你儘速理解程式碼裡面的問題。

錯誤一覽表
-----

In this list, each page is listed by name (the type of error) and message (a more detailed human-readable error message). Together, these two properties provide a starting point toward understanding and resolving the error. For more information, follow the links below!

* InternalError: too much recursion
* RangeError: invalid array length
* ReferenceError: "x" is not defined
* SyntaxError: missing } after property list
* SyntaxError: redeclaration of formal parameter "x"
* SyntaxError: return not in function
* TypeError: "x" has no properties
* TypeError: "x" is (not) "y"
* TypeError: "x" is not a function
參見
--

* 哪裡出錯了？JavaScript 除錯：針對初學者的 JavaScript 除錯入門教程。


標準內建物件 - JavaScript

標準內建物件
======

本章節記錄了 JavaScript 所有標準、內建的物件，以及這些物件的方法與屬性。

「全域物件」（或稱作標準內建物件）這個專有名字並非是要和**全域物件**混著說。在這裡，全域物件是那些在全域範圍裡的物件。而**全域物件**自身則是關聯到全域範圍裡的 `this` 運算子（但若是在 ECMAScript 5 的嚴格模式（strict mode）則是不被採用的，即會回傳 `undefined` (en-US)）。 事實上，全域範圍包含了全域物件的屬性，也包含了繼承而來的屬性（如果有的話）。

其他在全域範疇的物件，不是被使用者的腳本建立 (en-US)，就是由主體的應用程式所提供。 主體物件是由 API 參考資料 (en-US)定義的文件決定瀏覽器環境中是否可用。 更多關於 DOM (en-US) 和 JavaScript 核心的差異，請參考 JavaScript 技術概要。

標準物件分類
------

### 數值屬性

這些全域屬性會返回一個值；全域屬性本身不擁有任何屬性和函式。

* `Infinity`
* `NaN`
* `undefined` (en-US)
* `null` (en-US) literal
### 函數屬性

這些全域函式會直接在全域範圍中被呼叫，不用從某個物件取得後呼叫；呼叫後直接回傳結果給執行的人。

* `eval()` (en-US)
* `uneval()` (en-US)
非標準
* `isFinite()` (en-US)
* `isNaN()`
* `parseFloat()` (en-US)
* `parseInt()`
* `decodeURI()` (en-US)
* `decodeURIComponent()` (en-US)
* `encodeURI()` (en-US)
* `encodeURIComponent()` (en-US)
* `escape()` (en-US)
已棄用
* `unescape()` (en-US)
已棄用
### 基礎物件

這裡所陳列稱為基礎物件,將作為其他所有物件的母物件。包含了一般物件、函式以及錯誤。

* `Object` (en-US)
* `Function` (en-US)
* `Boolean`
* `Symbol` (en-US)
* `Error` (en-US)
* `EvalError` (en-US)
* `InternalError` (en-US)
* `RangeError`
* `ReferenceError` (en-US)
* `SyntaxError` (en-US)
* `TypeError` (en-US)
* `URIError`
### 數字與日期

這裡陳列了數字、日期及數學運算。

* `Number`
* `Math`
* `Date`
### 文字處理

These objects represent strings and support manipulating them.

* `String`
* `RegExp` (en-US)
### 具索引的集合

These objects represent collections of data which are ordered by an index value. This includes (typed) arrays and array-like constructs.

* `Array`
* `Int8Array` (en-US)
* `Uint8Array` (en-US)
* `Uint8ClampedArray` (en-US)
* `Int16Array` (en-US)
* `Uint16Array` (en-US)
* `Int32Array` (en-US)
* `Uint32Array` (en-US)
* `Float32Array` (en-US)
* `Float64Array` (en-US)
### 具鍵值的集合

These objects represent collections which use keys; these contain elements which are iterable in the order of insertion.

* `Map`
* `Set`
* `WeakMap` (en-US)
* `WeakSet` (en-US)
### 向量集合

SIMD (en-US) vector data types are objects where data is arranged into lanes.

* `SIMD`
實驗性質
* `SIMD.Float32x4`
實驗性質
* `SIMD.Float64x2`
實驗性質
* `SIMD.Int8x16`
實驗性質
* `SIMD.Int16x8`
實驗性質
* `SIMD.Int32x4`
實驗性質
* `SIMD.Uint8x16`
實驗性質
* `SIMD.Uint16x8`
實驗性質
* `SIMD.Uint32x4`
實驗性質
* `SIMD.Bool8x16`
實驗性質
* `SIMD.Bool16x8`
實驗性質
* `SIMD.Bool32x4`
實驗性質
* `SIMD.Bool64x2`
實驗性質
### 結構化資料

These objects represent and interact with structured data buffers and data coded using JavaScript Object Notation (JSON).

* `ArrayBuffer`
* `SharedArrayBuffer` (en-US)
實驗性質
* `Atomics` (en-US)
實驗性質
* `DataView` (en-US)
* `JSON`
### 控制抽象化物件

* `Promise`
* `Generator` (en-US)
* `GeneratorFunction` (en-US)
* 實驗性質
 `AsyncFunction` (en-US)
### Reflection

* `Reflect` (en-US)
* `Proxy` (en-US)
### 國際化

Additions to the ECMAScript core for language-sensitive functionalities.

* `Intl` (en-US)
* `Intl.Collator` (en-US)
* `Intl.DateTimeFormat` (en-US)
* `Intl.NumberFormat` (en-US)
### WebAssembly

* `WebAssembly` (en-US)
* `WebAssembly.Module` (en-US)
* `WebAssembly.Instance` (en-US)
* `WebAssembly.Memory` (en-US)
* `WebAssembly.Table` (en-US)
* `WebAssembly.CompileError` (en-US)
* `WebAssembly.LinkError` (en-US)
* `WebAssembly.RuntimeError` (en-US)
### 非標準物件

* `Iterator` (en-US)
非標準
* `ParallelArray`
非標準
* `StopIteration`
非標準
### 其他

* `arguments`


Classes - JavaScript

Classes
=======

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

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

* Learn more
* See full compatibility
* Report feedback

 類別 (class) 是在 ECMAScript 6 中引入，用來作為建立新物件的模板。它能將程式碼封裝起來便於處理。
 類別基於原型（prototype），但在語法和定義上，與 ES5 的類類別（class-like）有所不同。

定義類別
----

類別實際上是一種特別的函數(functions (en-US))，就跟你可以定義函數敘述和函數宣告一樣，類別的語法有兩個元件：類別敘述(class expressions (en-US))和類別宣告(class declarations (en-US))。

### 類別宣告

一個定義類別的方法是使用類別宣告(**class declaration**)，要宣告一個類別，你要使用關鍵字 `class` 搭配類別名稱(此例為 "Polygon")。

```js
class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
```

#### Hoisting

**函數宣告**和**類別宣告**的一個重要差別在於函數宣告是 hoisted ，類別宣告則不是。 你需要先宣告你的類別，然後存取它，否則像是下面的程式碼就會丟出一個 `ReferenceError` (en-US):

```js
var p = new Polygon(); // ReferenceError

class Polygon {}
```

### 類別敘述

**類別敘述**是定義類別的另一種方法。類別敘述可以有名稱或是無名稱。賦予一個有名稱類別敘述的名稱只在類別主體(class's body)中有作用。（但是類別敘述的名稱可以透過該類別（不是實例）的 .name (en-US) 屬性存取。）

```js
// unnamed
var Polygon = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

// named
var Polygon = class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
```

注意：類別**敘述**跟上述提到的類別**宣告**一樣，都會受到 hoisting 的影響。

類別主體與方法定義
---------

類別的主體指的是被大括號(`{}`)包含的部分，你可以在這裡面定義類別成員(members)，例如方法(methods)或建構子(constructors)。

### Strict mode

*類別宣告*與*類別敘述*的主體都會以嚴格模式(strict mode)執行，也就是說，建構子、靜態方法和原型方法、getter 及 setter 函數等都會以嚴格模式執行。

### 建構子

建構子(`constructor)`方法是一個特別的方法，用來建立和初始化一個`類別`的物件。一個類別只能有一個名為建構子(constructor)的特別方法。當類別中含有一個以上的`建構子`方法時，`SyntaxError` (en-US) 將會被拋出。

一個建構子可以用關鍵字 `super` 來呼叫父類別的建構子。

### 原型方法

參見 method definitions。

```js
class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // Method
  calcArea() {
    return this.height \* this.width;
  }
}

const square = new Polygon(10, 10);

console.log(square.area); //100
```

### 靜態方法(Static methods)

關鍵字 `static` 定義了一個類別的靜態方法，靜態方法不需要實體化它所屬類別的實例就可以被呼叫，它也**無法**被已實體化的類別物件呼叫。靜態方法經常被用來建立給應用程式使用的工具函數。

```js
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  static distance(a, b) {
    const dx = a.x - b.x;
    const dy = a.y - b.y;

    return Math.sqrt(dx \* dx + dy \* dy);
  }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);

console.log(Point.distance(p1, p2)); // 7.0710678118654755
```

### Instance properties

Instance properties 必須在 class 內定義:

```js
class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
```

### 宣告欄位

#### 宣告公共欄位

在 JavaScript 以宣告欄位改寫上面的程式，可以寫成如下：

```js
class Rectangle {
  height = 0;
  width;
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
```

通過事前宣告欄位，類別定義變得更加 self-documenting ，並且欄位會一直存在。

另外，如上面例子所示，聲明字段可以不用設定默認值。

想知道更多資訊，可參閱 public class fields (en-US)。

#### 宣告私有欄位

私有欄位的宣告，可以參考下方例子：

```js
class Rectangle {
  #height = 0;
  #width;
  constructor(height, width) {
    this.#height = height;
    this.#width = width;
  }
}
```

從類別外部使用私有欄位會出現錯誤；私有欄位只能在類別內讀寫。

通過宣告這些在類別以外不可見的東西，你可以確保類別的使用者不會倚賴類別的內部結構，畢竟一個類別的內部結構可能會隨著版本的更新而有所變化。

**備註：** 私有欄位只能在建立類別時事先宣告。

私有欄位不像普通欄位一樣，可以在類別宣告完後才建立。

想知道更多資訊，可參閱 private class features (en-US)。

### 裝箱、原型方法及靜態方法

當一個靜態方法或原形方法被呼叫，但沒有一個物件的值與 this 綁定時，被呼叫的函數中 this 關鍵字會是 **`undefined`**。在此情況下，自動裝箱（autoboxing）不會發生。即使我們在非嚴格模式中寫程式，此行為仍然會存在，這是因為所有的函式、定義方法、建構子、getter 和 setter 都是在嚴格模式中執行。因此，若我們沒有定義 this 的值，this 會是 **`undefined`**。

```js
class Animal {
  speak() {
    return this;
  }
  static eat() {
    return this;
  }
}

let obj = new Animal();
obj.speak(); // Animal {}
let speak = obj.speak;
speak(); // undefined

Animal.eat(); // class Animal
let eat = Animal.eat;
eat(); // undefined
```

若我們將上述程式用傳統的函式基礎類別(function based classes)表達，自動裝箱則會依據 this 在其被呼叫的函式中所綁定的值發生。

```js
function Animal() {}

Animal.prototype.speak = function () {
  return this;
};

Animal.eat = function () {
  return this;
};

let obj = new Animal();
let speak = obj.speak;
speak(); // 全域物件

let eat = Animal.eat;
eat(); // 全域物件
```

用 `extends` 建立子類別
-----------------

關鍵字 `extends` 是在類別宣告或是類別敘述中建立子類別的方法。

```js
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(this.name + " makes a noise.");
  }
}

class Dog extends Animal {
  speak() {
    console.log(this.name + " barks.");
  }
}

var d = new Dog("Mitzie");
d.speak(); // Mitzie barks.
```

若在子類別中有建構子(constructor)，要使用 this 前則必須先呼叫 super()函式。

你也可以擴充(extends)傳統的函式基礎"類別"。

```js
function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function () {
  console.log(this.name + " makes a noise.");
};

class Dog extends Animal {
  speak() {
    console.log(this.name + " barks.");
  }
}

var d = new Dog("Mitzie");
d.speak(); // Mitzie barks.
```

注意類別並無法擴充一般(non-constructible 不可建構的)物件。如果你想要繼承自一般的物件，可以使用`Object.setPrototypeOf()` (en-US)來達成。

```js
var Animal = {
  speak() {
    console.log(this.name + " makes a noise.");
  },
};

class Dog {
  constructor(name) {
    this.name = name;
  }
}

// 如果你沒有用以下的方法，當你呼叫speak時會出現TypeError
Object.setPrototypeOf(Dog.prototype, Animal);

var d = new Dog("Mitzie");
d.speak(); // Mitzie makes a noise.
```

Species
-------

你可能會希望在陣列的衍生類別 `MyArray` 中回傳陣列 (`Array`) ，Species 這個模式讓你能覆寫默認的建構子 (contructor)。

舉例來說，當你使用像 `map()` 這類會回傳默認建構子的方法時，你希望能回傳父物件 `Array` ，而不是 `MyArray` 物件。 `Symbol.species` (en-US) 符號讓你做到這件事：

```js
class MyArray extends Array {
  // Overwrite species to the parent Array constructor
  static get [Symbol.species]() {
    return Array;
  }
}

var a = new MyArray(1, 2, 3);
var mapped = a.map((x) => x \* x);

console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true
```

用 `super` 呼叫父類別
---------------

關鍵字 `super` 是用來提供一個類別呼叫其父類別的函數。

```js
class Cat {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(this.name + " makes a noise.");
  }
}

class Lion extends Cat {
  speak() {
    super.speak();
    console.log(this.name + " roars.");
  }
}

var l = new Lion("Fuzzy");
l.speak();
// Fuzzy makes a noise.
// Fuzzy roars.
```

ES5 繼承語法與 ES6 類別語法的比較
---------------------

TBD

範例
--

TBD

規格
--

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

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

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

參見
--

* Functions (en-US)
* `class` declaration (en-US)
* `class` expression (en-US)
* `super`
* Blog post: "ES6 In Depth: Classes"
* extends


運算式與運算子 - JavaScript

運算式與運算子
=======

本章節記錄了所有 JavaScript 運算式、運算子以及關鍵字。

運算式與運算子分類
---------

以字母排列的清單請參考左側的側邊欄。

### 主要運算式

在 JavaScript 中基本的關鍵字與一般的運算式。

`this`

`this` 關鍵字可以參考執行函數的所在位置。

`function` (en-US)

`function` 關鍵字可以定義一個函數運算式。

`class` (en-US)

`class` 關鍵字可以定義一個類別運算式。

`function*` (en-US)

`function*` 關鍵字可以定義一個 Generator 函數運算式

`yield` (en-US)

暫停與繼續一個產生器 (Generator) 函數。

`yield*` (en-US)

轉交另一個產生器 (Generator) 函數或可迭代 (Iterable) 的物件。

實驗性質 `async function*` (en-US)

`async` 函數可以定義一個非同步函數運算式。

實驗性質 `await`

暫停與繼續一個非同步函數並等候承諾的結果/拒絕。

`[]`

陣列初始化/書寫格式。

`{}` (en-US)

物件初始化/書寫格式。

`/ab+c/i` (en-US)

正規表示法書寫格式。

`( )` (en-US)

分組運算子。

### 左手邊運算式

左側值為賦值的目標。

Property accessors (en-US)

 成員運算子可存取物件的屬性或方法
 (`object.property` and `object["property"]`)。

`new`

`new` 運算子可以建立一個建構子 (Constructor) 的實例。

new.target (en-US)

在建構子中 `new.target` 可以參考被 `new` 呼叫的建構子 (Constructor) 。

`super`

`super` 關鍵字可以呼叫父建構子 (Constructor) 。

`...obj` (en-US)

The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.

### 遞增與遞減

字尾/字首遞增與字尾/字首遞減運算子。

`A++` (en-US)

字尾遞增運算子。

`A--` (en-US)

字尾遞減運算子。

`++A` (en-US)

字首遞增運算子。

`--A` (en-US)

字首遞減運算子。

### 一元運算子

一元運算是指只需要使用一個運算元的運算。

`delete`

`delete` 運算子可刪除物件中的屬性。

`void` (en-US)

`void` 運算子可放棄一個運算式的回傳值。

`typeof`

`typeof` 運算子可以判斷一個指定物件的型態。

`+` (en-US)

一元正運算子可以轉換其運算元成為數值 (Number) 型態。

`-` (en-US)

一元負運算子可以轉換其運算元成為數值 (Number) 型態並轉為負值。

`~` (en-US)

元位 NOT 運算子。

`!` (en-US)

邏輯 NOT 運算子。

### 算術運算子

算術運算子會要用到數值 (不論是字面值或者變數) 做為運算元，並且會回傳單一數值結果。

`+` (en-US)

加法運算子。

`-` (en-US)

減法運算子。

`/` (en-US)

除法運算子。

`*` (en-US)

乘法運算子。

`%` (en-US)

餘數運算子。

`**` (en-US)

指數運算子。

### 關係運算子

比較運算子會比較其運算元並根據比較的結果是否成立回傳一個 `Boolean` 值的結果。

`in` (en-US)

`in` 運算子會判斷一個物件是否有指定的屬性。

`instanceof` (en-US)

`instanceof` 運算子會判斷一個物件是否為另一個物件的實例。

`<` (en-US)

小於運算子。

`>` (en-US)

大於運算子。

`<=` (en-US)

小於等於運算子。

`>=` (en-US)

大於等於運算子。

**備註：** => is not an operator, but the notation for Arrow functions.

### 相等運算子

執行相對運算子後的結果為比較結果是否成立的 `Boolean` 值。

`==` (en-US)

相等運算子。

`!=` (en-US)

不相等運算子。

`===` (en-US)

恆等運算子。

`!==` (en-US)

不恆等運算子。

### 位元移位運算子

用來位移運算元所有位元的運算。

`<<` (en-US)

左移位元運算子。

`>>` (en-US)

右移位元運算子。

`>>>` (en-US)

右移無號位元運算子。

### 二元位元運算子

位元運算子將其運算元當做是 32 位元 (32 個零與一) 的數值處理並回傳標準 JavaScript 數值。

`&` (en-US)

位元 AND。

`|` (en-US)

位元 OR。

`^` (en-US)

位元 XOR。

### 二元邏輯運算子

邏輯運算子一般用在處理布林 (邏輯) 值，它們存在的地方會回傳一個布林 (Boolean) 值。

`&&` (en-US)

邏輯 AND。

`||` (en-US)

邏輯 OR。

### 條件 (三元) 運算子

`(condition ? ifTrue : ifFalse)`

條件運算子會根據條件的邏輯值判斷並回傳其中一個值。

### 賦值運算子

賦值運算子會根據其右側運算元的數值處理後賦值給其左側的運算元。

`=` (en-US)

賦值運算子。

`*=` (en-US)

乘法賦值。

`/=` (en-US)

除法賦值。

`%=` (en-US)

餘數賦值。

`+=` (en-US)

加法賦值。

`-=` (en-US)

減法賦值。

`<<=` (en-US)

左移賦值。

`>>=` (en-US)

右移賦值。

`>>>=` (en-US)

無號右移賦值。

`&=` (en-US)

位元 AND 賦值。

`^=` (en-US)

位元 XOR 賦值。

`|=` (en-US)

位元 OR 賦值。

`[a, b] = [1, 2]`
`{a, b} = {a:1, b:2}`

解構賦值讓你可使用如陣列或物件書寫格式來賦值給陣列或物件的屬性。

### 逗號運算子

`,` (en-US)

逗號運算子允許在一個敘述句中執行多個運算式並回傳最後一個運算式的結果。

### 非標準功能

非標準 Legacy generator function (en-US)

The `function` keyword can be used to define a legacy generator function inside an expression. To make the function a legacy generator, the function body should contains at least one `yield` (en-US) expression.

非標準 Expression closures

The expression closure syntax is a shorthand for writing simple function.

非標準 `[for (x of y) x]` (en-US)

Array comprehensions.

非標準 `(for (x of y) y)` (en-US)

Generator comprehensions.

技術規格
----

| Specification |
| --- |
| ECMAScript Language Specification # sec-addition-operator-plus |
| ECMAScript Language Specification # sec-assignment-operators |
| ECMAScript Language Specification # sec-async-function-definitions |
| ECMAScript Language Specification # sec-async-generator-function-definitions |
| ECMAScript Language Specification # prod-BitwiseANDExpression |
| ECMAScript Language Specification # sec-bitwise-not-operator |
| ECMAScript Language Specification # prod-BitwiseORExpression |
| ECMAScript Language Specification # prod-BitwiseXORExpression |
| ECMAScript Language Specification # sec-class-definitions |
| ECMAScript Language Specification # sec-comma-operator |
| ECMAScript Language Specification # sec-conditional-operator |
| ECMAScript Language Specification # sec-postfix-decrement-operator |
| ECMAScript Language Specification # sec-delete-operator |
| ECMAScript Language Specification # sec-destructuring-assignment |
| ECMAScript Language Specification # sec-destructuring-binding-patterns |
| ECMAScript Language Specification # sec-multiplicative-operators |
| ECMAScript Language Specification # sec-equality-operators |
| ECMAScript Language Specification # sec-exp-operator |
| ECMAScript Language Specification # sec-function-definitions |
| ECMAScript Language Specification # sec-generator-function-definitions |
| ECMAScript Language Specification # sec-relational-operators |
| ECMAScript Language Specification # sec-grouping-operator |
| ECMAScript Language Specification # sec-import-calls |
| ECMAScript Language Specification # prod-ImportMeta |
| HTML Standard # hostgetimportmetaproperties |
| ECMAScript Language Specification # sec-postfix-increment-operator |
| ECMAScript Language Specification # sec-left-shift-operator |
| ECMAScript Language Specification # prod-LogicalANDExpression |
| ECMAScript Language Specification # sec-logical-not-operator |
| ECMAScript Language Specification # prod-LogicalORExpression |
| ECMAScript Language Specification # sec-new-operator |
| ECMAScript Language Specification # sec-built-in-function-objects |
| ECMAScript Language Specification # sec-null-value |
| ECMAScript Language Specification # prod-CoalesceExpression |
| ECMAScript Language Specification # sec-object-initializer |
| ECMAScript Language Specification # prod-OptionalExpression |
| ECMAScript Language Specification # sec-property-accessors |
| ECMAScript Language Specification # sec-signed-right-shift-operator |
| ECMAScript Language Specification # prod-SpreadElement |
| ECMAScript Language Specification # prod-ArgumentList |
| ECMAScript Language Specification # prod-PropertyDefinition |
| ECMAScript Language Specification # sec-subtraction-operator-minus |
| ECMAScript Language Specification # sec-super-keyword |
| ECMAScript Language Specification # sec-this-keyword |
| ECMAScript Language Specification # sec-typeof-operator |
| ECMAScript Language Specification # sec-unary-minus-operator |
| ECMAScript Language Specification # sec-unary-plus-operator |
| ECMAScript Language Specification # sec-unsigned-right-shift-operator |
| ECMAScript Language Specification # sec-void-operator |
| ECMAScript Language Specification # prod-YieldExpression |
| ECMAScript Language Specification # sec-generator-function-definitions-runtime-semantics-evaluation |

相關文獻
----

* Operator precedence


extends - JavaScript

extends
=======

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

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

* Learn more
* See full compatibility
* Report feedback
**`extends`** 關鍵字被使用於類別（class）宣告 (en-US)或類別（class）表達式 (en-US)中來建立擴展的子類別 。

嘗試一下
----

語法
--
```

class ChildClass extends ParentClass { ... }
```

解釋
--

`extends` 關鍵字可用於建立一個自訂類別或內建類別的子類別。

其繼承之原型 `.prototype` 必須是 `Object` (en-US) 或 `null` (en-US)。

範例
--

### 使用 `extends`

第一個範例是根據 `Polygon`類別建立一個名為 `Square` 的子類別。此範例提取自線上示例。

```js
class Square extends Polygon {
  constructor(length) {
    // Here, it calls the parent class' constructor with lengths
    // provided for the Polygon's width and height
    super(length, length);
    // Note: In derived classes, super() must be called before you
    // can use 'this'. Leaving this out will cause a reference error.
    this.name = "Square";
  }

  get area() {
    return this.height \* this.width;
  }
}
```

### 使用 `extends` 於內建類別

這個範例擴展了內建的 `Date` 類別。此範例提取自線上範例。

```js
class myDate extends Date {
  constructor() {
    super();
  }

  getFormattedDate() {
    var months = [
      "Jan",
      "Feb",
      "Mar",
      "Apr",
      "May",
      "Jun",
      "Jul",
      "Aug",
      "Sep",
      "Oct",
      "Nov",
      "Dec",
    ];
    return (
      this.getDate() + "-" + months[this.getMonth()] + "-" + this.getFullYear()
    );
  }
}
```

### 擴展 `null`

像擴展普通類別一樣擴展 `null` (en-US)，但新對象的原型不會繼承 `Object.prototype` (en-US)。

```js
class nullExtends extends null {
  constructor() {}
}

Object.getPrototypeOf(nullExtends); // Function.prototype
Object.getPrototypeOf(nullExtends.prototype); // null

new nullExtends(); //ReferenceError: this is not defined
```

標準
--

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

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

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

參見
--

* Classes
* super


建構子 - JavaScript

建構子
===

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

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

* Learn more
* See full compatibility
* Report feedback
`constructor`（建構子）是個隨著 `class` 一同建立並初始化物件的特殊方法。

語法
--
```

constructor([arguments]) { ... }
```

敘述
--

一個 class 只能有一個稱為 constructor 的特殊物件。如果一個 class 出現兩次以上的 `constructor`，就會發生 `SyntaxError` (en-US) 錯誤。

如果不指定建構子，就會使用預設的建構子。

示例
--

### 使用 `constructor` 方法

這段程式碼是從 classes sample 擷取而來。（線上範例）

```js
class Square extends Polygon {
  constructor(length) {
    // 我們在這裡呼叫了 class 的建構子提供多邊形的長寬值
    super(length, length);
    // 注意：在 derived class 中，super() 必須在使用 this 以前被呼叫。不這樣的話會發生錯誤。
    this.name = "Square";
  }

  get area() {
    return this.height \* this.width;
  }

  set area(value) {
    this.area = value;
  }
}
```

### 預設的建構子

如上文所說：如果不指定建構子，就會使用預設的建構子。對 base classes 而言，預設的建構子長得像這樣：

```js
constructor() {}
```

對 derived class 而言，預設的建構子長得像這樣：

```js
constructor(...args) {
  super(...args);
}
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-static-semantics-constructormethod |

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

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

參見
--

* super()
* `class` expression (en-US)
* `class` declaration (en-US)
* Classes


static - JavaScript

static
======

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

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

* Learn more
* See full compatibility
* Report feedback
使用關鍵字 **static** 來定義一個靜態的方法（method）給類別（class），靜態方法在由類別所建立的物件實體（instance）上不能被呼叫，取而代之的是，靜態方法只能由類別本身呼叫。他們通常作為工具函式（utility functions）使用。像是建立物件或複製物件的函式。語法
--
```

static methodName() { ... }
```

敘述
--

靜態方法不須實例化(instantiating)其類別即可被呼叫，但當類別被實例化(instantiating)後則靜態方法不能被呼叫。 靜態方法常被使用在建立應用程式的工具函式(utility functions)。

範例
--

下面的範例示範了許多東西。他示範了如何在一個可以有子類別的類別中實作一個靜態方法。最後示範了靜態方法在什麼情形下正確與錯誤的呼叫。

```js
class Triple {
  static triple(n) {
    n = n || 1; //should not be a bitwise operation
    return n \* 3;
  }
}

class BiggerTriple extends Triple {
  static triple(n) {
    return super.triple(n) \* super.triple(n);
  }
}

console.log(Triple.triple()); // 3
console.log(Triple.triple(6)); // 18
console.log(BiggerTriple.triple(3)); // 81
var tp = new Triple();
console.log(tp.triple()); // 'tp.triple is not a function'.
```

規格
--

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

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

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

你可能會需要看看
--------

* `class` expression (en-US)
* `class` declaration (en-US)
* Classes


字串 - JavaScript

字串
==

**`String`** 全域物件為字串的構造函數，或是一個字符序列。

語法
--

字串文字採用下列形式：
```

'string text' "string text" "中文 español deutsch English हिन्दी العربية português বাংলা русский 日本語 ਪੰਜਾਬੀ 한국어 தமிழ் עברית"
```

字串也可以被全域的 `String` 物件建立：
```

String(thing)
```

### 參數

`thing`

任何要轉換成字串的物件。

### 樣板字面值

自 ECMAScript 2015，字串文字也可以是樣板字面值（Template literals）：
```

`hello world` `hello! world!` `hello ${who}` escape `<a>${who}</a>`
```

### 跳脫符號

除了常規的、可印出來的字元，特殊字元也可以被跳脫符號來表示編碼。

| 代碼 | 輸出 |
| --- | --- |
| `\0` | 空字元 |
| `\'` | 單引號 |
| `\"` | 雙引號 |
| `\\` | 反斜線 |
| `\n` | 斷行 |
| `\r` | 回車 |
| `\v` | 垂直制表 |
| `\t` | 制表 |
| `\b` | 退格 |
| `\f` | 饋頁 |
| `\uXXXX` | unicode 代碼 |
| `\u{X}` ... `\u{XXXXXX}` | unicode 代碼
實驗性質
 |
| `\xXX` | Latin-1 字元 |

**備註：** 和其他語言不同，JavaScript 將單引號字串和雙引號字串是做相同；因此，上述的序列可以在單引號或雙引號中作用。

### 長字面值字串

有些時候，你的程式碼會包含非常長的字串。 為了不讓長字串無止盡地往下長，抑或是在你心血來潮的時候，你可能希望將這樣長的字串能夠斷成多行卻不影響到實際的內容。

你可以用 + 運算子附加多個字串在一起，像是這樣：

```js
let longString =
  "This is a very long string which needs " +
  "to wrap across multiple lines because " +
  "otherwise my code is unreadable.";
```

或者，你可以在每一行尾端用反斜線字元（"\"）表示字串會繼續被顯示在下一列。 你必須要確定在反斜線後面沒有任何空白或其他字元，甚至是縮排；否則這個方法將失效。 這個形式看起來像這樣：

```js
let longString =
  "This is a very long string which needs \
to wrap across multiple lines because \
otherwise my code is unreadable.";
```

這兩個方法都會建立相同的字串內容。

說明
--

字串對於能保留以文字形式表達的資料這件事來說，是有用的。在字串上，一些最常被使用的運算即確認字串長度 `length` (en-US) ，用 + 或 += 字串運算元 建造或者串接字串，用 `indexOf` (en-US) 方法檢查?子字串是否存在或子字串的位置，或者是用 `substring` (en-US) 方法將子字串抽取出來。

### 存取字元

有兩個方法可以存取字串中個別的字元。第一個是用 `charAt` (en-US) 方法：

```js
return "cat".charAt(1); // 回傳 "a"
```

另一個(在 ECMAScript 5 中被提到)方法是將字串當作一個類似陣列的物件，直接存取字串中對應的數值索引。

```js
return "cat"[1]; // 回傳 "a"
```

對於存取字元使用的括號表達式，沒辦法去刪除或指派一個值給這些屬性。 這些屬性既非可寫的，也非可設定的。(參見 `Object.defineProperty`)

### 比較字串

C 語言的開發者有 `strcmp()` 函式可以用來比較字串。 在 JavaScript 中，你只能用小於和大於運算子 (en-US)：

```js
var a = "a";
var b = "b";
if (a < b)
  // true
  print(a + " 小於 " + b);
else if (a > b) print(a + " 大於 " + b);
else print(a + " 和 " + b + " 相等");
```

這樣類似的結果，也能使用繼承 `String` 實體的 `localeCompare` 方法來實現。

### 分辨 string 原始型別和 `String` 物件

請注意，JavaScript 會區別 `String` 物件和原始字串(`Boolean` 和 `Numbers` 也是如此)。

String literals (denoted by double or single quotes) and strings returned from `String` calls in a non-constructor context (i.e., without using the `new` keyword) are primitive strings. JavaScript automatically converts primitives to `String` objects, so that it's possible to use `String` object methods for primitive strings. In contexts where a method is to be invoked on a primitive string or a property lookup occurs, JavaScript will automatically wrap the string primitive and call the method or perform the property lookup.

```js
var s_prim = "foo";
var s_obj = new String(s_prim);

console.log(typeof s_prim); // 印出 "string"
console.log(typeof s_obj); // 印出 "object"
```

字串原始型別和 `String` 物件也會在使用 `eval` (en-US) 時給出不同的結果。 原始型別傳進 `eval` 會被視為原始代碼；`String` 物件則會回傳，且被視作是其他物件。舉個例子：

```js
s1 = "2 + 2"; // 建立一個字串原始型別
s2 = new String("2 + 2"); // 建立一個字串物件
console.log(eval(s1)); // 回傳數字 4
console.log(eval(s2)); // 回傳字串 "2 + 2"
```

因為一些原因，程式碼也許在遇到 `String` 物件時，但需要的卻是字串原始型別；儘管如此，通常作者們不需要擔心它的差異。

一個 `String` 物件總能夠使用 `valueOf` (en-US) 方法被轉換成自身的原始副本。

```js
console.log(eval(s2.valueOf())); // 回傳數字 4
```

屬性
--

`String.prototype` (en-US)

能讓字串物件增加屬性。

方法
--

`String.fromCharCode()` (en-US)

利用 Unicode 值的序列建立並回傳一個字串。

`String.fromCodePoint()` (en-US)
實驗性質

利用編碼位置的序列建立並回傳一個字串。

`String` 通用方法
-------------

**警告：** 字串通用方法是非標準化的、被棄用的，也有近期將被刪除的。

The `String` instance methods are also available in Firefox as of JavaScript 1.6 (though not part of the ECMAScript standard) on the String object for applying String methods to any object:

```js
var num = 15;
alert(String.replace(num, /5/, "2"));
```

Generics are also available on `Array` methods.

The following is a shim to provide support to non-supporting browsers:

```js
/\*globals define\*/
// Assumes all supplied String instance methods already present
// (one may use shims for these if not available)
(function () {
  "use strict";

  var i,
    // We could also build the array of methods with the following, but the
    // getOwnPropertyNames() method is non-shimable:
    // Object.getOwnPropertyNames(String).filter(function (methodName)
    // {return typeof String[methodName] === 'function'});
    methods = [
      "quote",
      "substring",
      "toLowerCase",
      "toUpperCase",
      "charAt",
      "charCodeAt",
      "indexOf",
      "lastIndexOf",
      "startsWith",
      "endsWith",
      "trim",
      "trimLeft",
      "trimRight",
      "toLocaleLowerCase",
      "toLocaleUpperCase",
      "localeCompare",
      "match",
      "search",
      "replace",
      "split",
      "substr",
      "concat",
      "slice",
    ],
    methodCount = methods.length,
    assignStringGeneric = function (methodName) {
      var method = String.prototype[methodName];
      String[methodName] = function (arg1) {
        return method.apply(arg1, Array.prototype.slice.call(arguments, 1));
      };
    };

  for (i = 0; i < methodCount; i++) {
    assignStringGeneric(methods[i]);
  }
})();
```

`String` instances
------------------

### Properties

`String.prototype.length` (en-US)

Reflects the `length` of the string. Read-only.

### Methods

`String.prototype.at()` (en-US)

Returns the character (exactly one UTF-16 code unit) at the specified `index`. Accepts negative integers, which count back from the last string character.

`String.prototype.charAt()` (en-US)

 Returns the character (exactly one UTF-16 code unit) at the specified
 `index`.

`String.prototype.charCodeAt()` (en-US)

 Returns a number that is the UTF-16 code unit value at the given
 `index`.

`String.prototype.codePointAt()` (en-US)

 Returns a nonnegative integer Number that is the code point value of the UTF-16
 encoded code point starting at the specified `pos`.

`String.prototype.concat()`

Combines the text of two (or more) strings and returns a new string.

`String.prototype.includes()` (en-US)

Determines whether the calling string contains `searchString`.

`String.prototype.endsWith()` (en-US)

 Determines whether a string ends with the characters of the string
 `searchString`.

`String.prototype.indexOf()` (en-US)

 Returns the index within the calling `String` object of the first
 occurrence of `searchValue`, or `-1` if not found.

`String.prototype.lastIndexOf()` (en-US)

 Returns the index within the calling `String` object of the last
 occurrence of `searchValue`, or `-1` if not found.

`String.prototype.localeCompare()`

 Returns a number indicating whether the reference string
 `compareString` comes before, after, or is equivalent to the
 given string in sort order.

`String.prototype.match()` (en-US)

Used to match regular expression `regexp` against a string.

`String.prototype.matchAll()` (en-US)

Returns an iterator of all `regexp`'s matches.

`String.prototype.normalize()` (en-US)

Returns the Unicode Normalization Form of the calling string value.

`String.prototype.padEnd()` (en-US)

 Pads the current string from the end with a given string and returns a new string of
 the length `targetLength`.

`String.prototype.padStart()`

 Pads the current string from the start with a given string and returns a new string
 of the length `targetLength`.

`String.prototype.repeat()` (en-US)

 Returns a string consisting of the elements of the object repeated
 `count` times.

`String.prototype.replace()` (en-US)

 Used to replace occurrences of `searchFor` using
 `replaceWith`. `searchFor` may be a string
 or Regular Expression, and `replaceWith` may be a string or
 function.

`String.prototype.replaceAll()` (en-US)

 Used to replace all occurrences of `searchFor` using
 `replaceWith`. `searchFor` may be a string
 or Regular Expression, and `replaceWith` may be a string or
 function.

`String.prototype.search()` (en-US)

 Search for a match between a regular expression `regexp` and
 the calling string.

`String.prototype.slice()` (en-US)

Extracts a section of a string and returns a new string.

`String.prototype.split()` (en-US)

 Returns an array of strings populated by splitting the calling string at occurrences
 of the substring `sep`.

`String.prototype.startsWith()` (en-US)

 Determines whether the calling string begins with the characters of string
 `searchString`.

`String.prototype.substring()` (en-US)

 Returns a new string containing characters of the calling string from (or between)
 the specified index (or indices).

`String.prototype.toLocaleLowerCase()` (en-US)

 The characters within a string are converted to lowercase while respecting the
 current locale.

 For most languages, this will return the same as
 `toLowerCase()`.

`String.prototype.toLocaleUpperCase( [locale, ...locales])` (en-US)

 The characters within a string are converted to uppercase while respecting the
 current locale.

 For most languages, this will return the same as
 `toUpperCase()` (en-US).

`String.prototype.toLowerCase()`

Returns the calling string value converted to lowercase.

`String.prototype.toString()` (en-US)

 Returns a string representing the specified object. Overrides the
 `Object.prototype.toString()` (en-US) method.

`String.prototype.toUpperCase()` (en-US)

Returns the calling string value converted to uppercase.

`String.prototype.trim()`

Trims whitespace from the beginning and end of the string.

`String.prototype.trimStart()` (en-US)

Trims whitespace from the beginning of the string.

`String.prototype.trimEnd()` (en-US)

Trims whitespace from the end of the string.

`String.prototype.valueOf()` (en-US)

 Returns the primitive value of the specified object. Overrides the
 `Object.prototype.valueOf()` (en-US) method.

`String.prototype[@@iterator]()` (en-US)

 Returns a new iterator object that iterates over the code points of a String value,
 returning each code point as a String value.

Examples
--------

### String conversion

It's possible to use `String` as a "safer" `toString` (en-US) alternative, as although it still normally calls the underlying `toString`, it also works for `null` and `undefined`. For example:

```js
var outputStrings = [];
for (let i = 0, n = inputValues.length; i < n; ++i) {
  outputStrings.push(String(inputValues[i]));
}
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-string-objects |

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

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

參見
--

* `DOMString`
* `StringView` — a C-like representation of strings based on typed arrays
* Binary strings


BigInt - JavaScript

BigInt
======

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

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

* Learn more
* See full compatibility
* Report feedback
**實驗性質:** **這是一個實驗中的功能 (en-US)**
此功能在某些瀏覽器尚在開發中，請參考兼容表格以得到不同瀏覽器用的前輟。

`BigInt` 是一個內建的物件，提供了表示大於 2^53 的整數的功能 (2^53 是 JavaScript 原生的`Number`能夠表示的最大值)

語法
--

```js
BigInt(value);
```

### 參數

`value`

欲創建的數值，可以為整數或字串。

**備註：** `BigInt()` 不和 `new` 一起使用。

說明
--

`BigInt` 是透過在一個數值後加上 `n` ，例如 `10n` ，或呼叫 `BigInt()` 所生成的。

```js
const theBiggestInt = 9007199254740991n;

const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n

const hugeString = BigInt("9007199254740991");
// ↪ 9007199254740991n

const hugeHex = BigInt("0x1fffffffffffff");
// ↪ 9007199254740991n

const hugeBin = BigInt(
  "0b11111111111111111111111111111111111111111111111111111",
);
// ↪ 9007199254740991n
```

`BigInt` 跟 `Number` 很像，但在某些部分有些許不同 — 它不可以被用在內建的 `Math` 物件方法中、而且不可以跟 `Number` 的實體混用運算子。

**警告：** `Number` 和 `BigInt` 不能混和計算 — 他們必須被轉換到同一個型態。

然而，在相互轉換時要注意， `BigInt` 在被轉換成 `Number` 時可能會遺失部分精度的資訊。

### 類別資訊

當使用 `typeof` 測試時，一個 `BigInt` 會回傳 "bigint"：

```js
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true
```

當使用 `Object` 來包裹時，`BigInt` 會被看成是普通的 "object" 型態：

```js
typeof Object(1n) === "object"; // true
```

### Operator

下列的運算子可以被用在 `BigInt` 上 (或由 object 包裹的 `BigInt`): `+`, `*`, `-`, `**`, `%`.

```js
const previousMaxSafe = BigInt(Number.MAX\_SAFE\_INTEGER);
// ↪ 9007199254740991

const maxPlusOne = previousMaxSafe + 1n;
// ↪ 9007199254740992n

const theFuture = previousMaxSafe + 2n;
// ↪ 9007199254740993n, this works now!

const multi = previousMaxSafe \* 2n;
// ↪ 18014398509481982n

const subtr = multi – 10n;
// ↪ 18014398509481972n

const mod = multi % 10n;
// ↪ 2n

const bigN = 2n \*\* 54n;
// ↪ 18014398509481984n

bigN \* -1n
// ↪ –18014398509481984n
```

`/` 運算子也同樣的能夠運行。然而，因為型態是 `BigInt` 而不是 `BigDecimal` ，除法運算會無條件捨去小數。也就是說，回傳值不會包含小數部分。

**警告：** 回傳值帶小數的運算在使用`BigInt` 時小數部分會被捨去。

```js
const expected = 4n / 2n;
// ↪ 2n

const rounded = 5n / 2n;
// ↪ 2n, not 2.5n
```

### 比較

一個 `BigInt` 並不嚴格等於一個 `Number`，但他們會一般相等。

```js
0n === 0;
// ↪ false

0n == 0;
// ↪ true
```

一個 `Number` 和 `BigInt` 可以像普通運算一樣比較。

```js
1n < 2;
// ↪ true

2n > 1;
// ↪ true

2 > 2;
// ↪ false

2n > 2;
// ↪ false

2n >= 2;
// ↪ true
```

他們可以參雜在陣列中並照預期的被排序。

```js
const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
// ↪ [4n, 6, -12n, 10, 4, 0, 0n]

mixed.sort();
// ↪ [-12n, 0, 0n, 10, 4n, 4, 6]
```

Note that comparisons with `Object`-wrapped `BigInt`s act as with other objects, only indicating equality when the same object instance is compared:

```js
0n === Object(0n); // false
Object(0n) === Object(0n); // false

const o = Object(0n);
o === o; // true
```

### Conditional

A `BigInt` behaves like a `Number` in cases where it is converted to a `Boolean`: via the `Boolean` function; when used with logical operators `Logical Operators` (en-US) `||`, `&&`, and `!`; or within a conditional test like an `if statement`.

```js
if (0n) {
  console.log("Hello from the if!");
} else {
  console.log("Hello from the else!");
}

// ↪ "Hello from the else!"

0n || 12n;
// ↪ 12n

0n && 12n;
// ↪ 0n

Boolean(0n);
// ↪ false

Boolean(12n);
// ↪ true

!12n;
// ↪ false

!0n;
// ↪ true
```

方法
--

`BigInt.asIntN()` (en-US)

Clamps a BigInt value to a signed integer value, and returns that value.

`BigInt.asUintN()` (en-US)

Clamps a BigInt value to an unsigned integer value, and returns that value.

屬性
--

`BigInt.prototype`

允許對一個 `BigInt` 物件增加其屬性。

`BigInt` 物件實體
-------------

All `BigInt` instances inherit from `BigInt.prototype`. The prototype object of the `BigInt` constructor can be modified to affect all `BigInt` instances.

### 方法

`BigInt.prototype.toLocaleString()` (en-US)

Returns a string with a language-sensitive representation of this BigInt value. Overrides the `Object.prototype.toLocaleString()` (en-US) method.

`BigInt.prototype.toString()` (en-US)

Returns a string representing this BigInt value in the specified radix (base). Overrides the `Object.prototype.toString()` (en-US) method.

`BigInt.prototype.valueOf()` (en-US)

Returns this BigInt value. Overrides the `Object.prototype.valueOf()` (en-US) method.

建議用法
----

### 轉型

因為在 `Number` 和 `BigInt` 之間轉換可能造成精度遺失，建議當數值會超過 2^53 時只使用 `BigInt` ，而不要在兩者之間進行轉換。

### 加密

`BigInt` 支援的運算並非常數時間。因此 `BigInt` 不適用在加密學上。

範例
--

### 計算質數

```js
function isPrime(p) {
  for (let i = 2n; i \* i <= p; i++) {
    if (p % i === 0n) return false;
  }
  return true;
}

// Takes a BigInt as an argument and returns a BigInt
function nthPrime(nth) {
  let maybePrime = 2n;
  let prime = 0n;

  while (nth >= 0n) {
    if (isPrime(maybePrime)) {
      nth -= 1n;
      prime = maybePrime;
    }
    maybePrime += 1n;
  }

  return prime;
}

nthPrime(20n);
// ↪ 73n
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-bigint-objects |

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

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

參見
--

* `Number`


URIError - JavaScript

URIError
========

**`URIError`** 物件在全域的 URI 處理函式被錯誤使用時作為一個錯誤被拋出。

語法
--
```

new URIError([message[, fileName[, lineNumber]]])
```

### 參數

`message`

可選。具人類可讀性的錯誤說明

`fileName`
非標準

可選。包含造成錯誤發生的程式碼的檔案名稱

`lineNumber`
非標準

可選。造成錯誤發生的程式碼行號

說明
--

`URIError` 在全域的 URI 處理函式被傳入了一個錯誤編碼的 URI 時被拋出。

屬性
--

`URIError.prototype` (en-US)

允許對一個 `URIError` 物件增加其屬性。

方法
--

普遍的 `URIError` 自身沒有包含方法，儘管他的確從原型鍊中繼承了一些。

`URIError` 物件實體
---------------

### 屬性

`URIError.prototype.message` (en-US)

Error message. Inherited from `Error` (en-US).

`URIError.prototype.name` (en-US)

Error name. Inherited from `Error` (en-US).

`URIError.prototype.cause` (en-US)

Error cause. Inherited from `Error` (en-US).

`URIError.prototype.fileName` (en-US)
非標準

Path to file that raised this error. Inherited from `Error` (en-US).

`URIError.prototype.lineNumber` (en-US)
非標準

Line number in file that raised this error. Inherited from `Error` (en-US).

`URIError.prototype.columnNumber`
非標準

Column number in line that raised this error. Inherited from `Error` (en-US).

`URIError.prototype.stack` (en-US)
非標準

Stack trace. Inherited from `Error` (en-US).

範例
--

### Catch 一個 `URIError`

```js
try {
  decodeURIComponent("%");
} catch (e) {
  console.log(e instanceof URIError); // true
  console.log(e.message); // "malformed URI sequence"
  console.log(e.name); // "URIError"
  console.log(e.fileName); // "Scratchpad/1"
  console.log(e.lineNumber); // 2
  console.log(e.columnNumber); // 2
  console.log(e.stack); // "@Scratchpad/2:2:3\n"
}
```

### 生成一個 `URIError`

```js
try {
  throw new URIError("Hello", "someFile.js", 10);
} catch (e) {
  console.log(e instanceof URIError); // true
  console.log(e.message); // "Hello"
  console.log(e.name); // "URIError"
  console.log(e.fileName); // "someFile.js"
  console.log(e.lineNumber); // 10
  console.log(e.columnNumber); // 0
  console.log(e.stack); // "@Scratchpad/2:2:9\n"
}
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-native-error-types-used-in-this-standard-urierror |

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

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

參見
--

* `Error` (en-US)
* `URIError.prototype` (en-US)
* `decodeURI()` (en-US)
* `decodeURIComponent()` (en-US)
* `encodeURI()` (en-US)
* `encodeURIComponent()` (en-US)


parseInt() - JavaScript

parseInt()
==========

**`parseInt()`** 函式能將輸入的字串轉成整數。

嘗試一下
----

語法
--

```js
parseInt(string, radix);
```

### 參數

`string`

待轉成數字的字串。若 `string` 參數類型不是字串的話，會先將其轉成字串（相當於先執行 `ToString` 再執行 `parseInt`）空白值會被忽略。

`radix`

從 2 到 36，能代表該進位系統的數字。例如說指定 `10` 就等於指定十進位。**一定要定義這個參數**以避免他人的困惑、也好預估函式的行為。如果沒有指定 radix 的話，給出的結果會按照實做不同而異，請注意，通常預設值**不是** 10 進位。

### 回傳值

藉由給定字串作轉換後的數字。若第一個字符無法轉換為數字，則回傳 `NaN`。

說明
--

`parseInt` 函式會把第一個參數變成字串、解析它、再回傳整數或是 `NaN`。如果不是 `NaN`，回傳值會把第一個參數，參照指定的 *radix* 後，以十進位表示。例如，*radix* 指定為 10 的話，它會以十進位為單位轉換、8 是八進位、16 是十六進位，依此類推。For radices above `10`, the letters of the alphabet indicate numerals greater than `9`. For example, for hexadecimal numbers (base 16), `A` through `F` are used.

如果說 `parseInt` 碰上了無法被 radix 指定的進位制所轉換的字元，它會忽略該字元、以及其後所有字元，並只回傳至該位置為止的解析數值結果。`parseInt` 將數字擷取、轉換成整數數值。 可以接受字串首尾出現空白。

Because some numbers include the `e` character in their string representation (e.g. **`6.022e23`**), using `parseInt` to truncate numeric values will produce unexpected results when used on very large or very small numbers. `parseInt` should not be used as a substitute for `Math.floor()`.

如果 *radix* 是 `undefined` 或 0（或留空）的話，JavaScript 會：

* 如果 `string` 由 "0x" 或 "0X" 開始，*radix* 會變成代表十六進位的 16，並解析字串的餘數。
* 如果 `string` 由 0 開始，則 *radix* 會變成代表八進位的 8 或十進位的 10，但到底會變成 8 還是 10 則取決於各實做。ECMAScript 規定用代表十進位的 10，但也不是所有瀏覽器都支持。因此，**使用 `parseInt` 時一定要指定 radix**。
* 如果 `string` 由其他字串開始，radix 就會是十進位的 10。

如果第一個字串無法被解析為任何數字，`parseInt` 會回傳 `NaN`。

For arithmetic purposes, the `NaN` value is not a number in any radix. You can call the `isNaN` function to determine if the result of `parseInt` is `NaN`. If `NaN` is passed on to arithmetic operations, the operation results will also be `NaN`.

若想將數字轉成特定的進位制，可使用 `intValue.toString(radix)`。

範例
--

### 使用 `parseInt`

以下的範例，回傳的值均為 **`15`**：

```js
parseInt(" 0xF", 16);
parseInt(" F", 16);
parseInt("17", 8);
parseInt(021, 8);
parseInt("015", 10); // parseInt(015, 10); will return 15
parseInt(15.99, 10);
parseInt("15,123", 10);
parseInt("FXX123", 16);
parseInt("1111", 2);
parseInt("15\*3", 10);
parseInt("15e2", 10);
parseInt("15px", 10);
parseInt("12", 13);
```

以下均回傳 **`NaN`**：

```js
parseInt("Hello", 8); // 根本不是數字
parseInt("546", 2); // 在二進位無效
```

以下的範例，回傳的值均為 **`-15`**：

```js
parseInt("-F", 16);
parseInt("-0F", 16);
parseInt("-0XF", 16);
parseInt(-15.1, 10);
parseInt(" -17", 8);
parseInt(" -15", 10);
parseInt("-1111", 2);
parseInt("-15e1", 10);
parseInt("-12", 13);
```

下例會回傳 **`4`**：

```js
parseInt(4.7, 10);
parseInt(4.7 \* 1e22, 10); // Very large number becomes 4
parseInt(0.00000000000434, 10); // Very small number becomes 4
```

下例會回傳 **`224`**:

```js
parseInt("0e0", 16);
```

無 radix 情況下的八進制
---------------

雖說已在 ECMAScript 3 提議並於 ECMAScript 5 禁用，但部分 javascript 編譯器仍會在特殊情況下，將 str 視作八進位數字（當數字以 `0` 開頭時）。以下為可能發生這種問題的情況：（**永遠要宣告 radix 以避開這不可靠的行為**）

```js
parseInt("0e0"); // 0
parseInt("08"); // 0, '8' is not an octal digit.
```

### ECMAScript 5 移除八進位轉譯（octal interpretation）

The ECMAScript 5 specification of the function `parseInt` no longer allows implementations to treat Strings beginning with a `0` character as octal values. ECMAScript 5 states:

The `parseInt` function produces an integer value dictated by interpretation of the contents of the string argument according to the specified radix. Leading white space in string is ignored. If radix is undefined or `0`, it is assumed to be `10` except when the number begins with the character pairs `0x` or `0X`, in which case a radix of 16 is assumed.

This differs from ECMAScript 3, which discouraged but allowed octal interpretation.

Many implementations have not adopted this behavior as of 2013, and because older browsers must be supported, **always specify a radix**.

嚴謹的解析 function
--------------

有的時候，使用更嚴謹的 code 能夠更精確地轉換整數值。Regular expression 可以幫你：

```js
filterInt = function (value) {
  if (/^(\-|\+)?([0-9]+|Infinity)$/.test(value)) return Number(value);
  return NaN;
};

console.log(filterInt("421")); // 421
console.log(filterInt("-421")); // -421
console.log(filterInt("+421")); // 421
console.log(filterInt("Infinity")); // Infinity
console.log(filterInt("421e+0")); // NaN
console.log(filterInt("421hop")); // NaN
console.log(filterInt("hop1.61803398875")); // NaN
console.log(filterInt("1.61803398875")); // NaN
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-parseint-string-radix |

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

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

參見
--

* `parseFloat()` (en-US)
* `Number.parseFloat()` (en-US)
* `Number.parseInt()` (en-US)
* `isNaN()`
* `Number.toString()` (en-US)
* `Object.valueOf` (en-US)


Infinity - JavaScript

Infinity
========

全域 **`Infinity`** 屬性是一個表示無窮大的數值。

| `Infinity` 的屬性特性 |
| --- |
| 可寫 | 否 |
| 可列舉 | 否 |
| 可配置 | 否 |

語法
--

```js
Infinity
```

描述
--

`Infinity` 是全域物件屬性，即它是全域範圍內的變數。

`Infinity` 的初始值是 `Number.POSITIVE_INFINITY` (en-US) `Infinity` 值（正無窮大）值大於其他任何數值。該值在數學上表現為無窮大。例如，任何乘以 `Infinity` 的正整數都是 `Infinity`，除以 `Infinity` 的任何數都是 0。

按照 ECMAScript 5 規範，在 JavaScript 1.8.5 / Firefox 4 實作的 `Infinity` 乃唯讀屬性。

範例
--

```js
console.log(Infinity); /\* Infinity \*/
console.log(Infinity + 1); /\* Infinity \*/
console.log(Math.pow(10, 1000)); /\* Infinity \*/
console.log(Math.log(0)); /\* -Infinity \*/
console.log(1 / Infinity); /\* 0 \*/
```

規範
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-value-properties-of-the-global-object-infinity |

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

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

參見
--

* `Number.NEGATIVE_INFINITY` (en-US)
* `Number.POSITIVE_INFINITY` (en-US)
* `Number.isFinite` (en-US)