recursal/MDN huggingface dataset:
setter
======

**`set`** 語法會在物件屬性被嘗試定義時，將其屬性綁定到要呼叫的函式內。

嘗試一下
----

語法
--
```

{set prop(val) { . . . }}
{set [expression](val) { . . . }}
```

### 參數

`prop`

要綁定到給定函式的屬性名。

`val`

變數別名，該變數擁有要被嘗試安插到 `prop` 的數值。

expression

從 ECMAScript 2015 開始，可以使用計算屬性名（computed property name）表達式，綁定到給定函式。

描述
--

JavaScript 的 setter 能在嘗試修改指定屬性時，執行給定函式。Setter 最常用於和 getter 一同建立虛擬屬性（pseudo-property）。你不可能給同一個屬性賦予 setter 與實際值。

使用 `set` 語法時，請注意以下情況：

* 可以擁有一個以數字或字串為代表的標示符；
* 最少要有一個參數（請參見 Incompatible ES5 change: literal getter and setter functions must now have exactly zero or one arguments 的詳細資料）；
* 不能以有另一個 `set` 的 object literal、或相同屬性入口（data entry）的 data 形式出現（不能使用 `{ set x(v) { }, set x(v) { } }` and `{ x: ..., set x(v) { } }`）

`delete` 操作符可移除 setter。

示例
--

### 在物件初始器的新物件定義 setter

這裡會給物件 `language` 定義稱為 `current` 的虛擬屬性。在指派數值時 `log` 會和該值一同更新：


```js
var language = {
  set current(name) {
    this.log.push(name);
  },
  log: [],
};

language.current = "EN";
console.log(language.log); // ['EN']

language.current = "FA";
console.log(language.log); // ['EN', 'FA']
```


請注意 `current` is not defined and any attempts to access it will result in `undefined`.

### 使用 `delete` 操作符移除 setter

若想移除 setter 的話，可以直接使用 `delete`：


```js
delete o.current;
```

### 針對已存在屬性的 setter 使用 `defineProperty`

To append a setter to an existing object later at any time, use `Object.defineProperty()`.


```js
var o = { a: 0 };

Object.defineProperty(o, "b", {
  set: function (x) {
    this.a = x / 2;
  },
});

o.b = 10; // Runs the setter, which assigns 10 / 2 (5) to the 'a' property
console.log(o.a); // 5
```

### 使用計算屬性名


```js
var expr = "foo";

var obj = {
  baz: "bar",
  set [expr](v) {
    this.baz = v;
  },
};

console.log(obj.baz); // "bar"
obj.foo = "baz"; // 跑 setter
console.log(obj.baz); // "baz"
```

規範
--

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

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

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

參見
--

* getter
* `delete`
* `Object.defineProperty()`
* `Object.prototype.__defineGetter__()` (en-US)
* `Object.prototype.__defineSetter__()` (en-US)
* JavaScript 教學的定義 Getters 與 Setters (en-US)
方法定義
====

自 ECMAScript 2015 開始，引入了一種於物件初始器（objects initializers）中定義方法的簡短語法。是一個將函式指派予方法名稱的簡便方式。

嘗試一下
----

語法
--
```

var obj = {
  property( parameters… ) {},
  *generator( parameters… ) {},
  async property( parameters… ) {},
  async* generator( parameters… ) {},

  // with computed keys:
  [property]( parameters… ) {},
  *[generator]( parameters… ) {},
  async [property]( parameters… ) {},

  // compare getter/setter syntax:
  get property() {},
  set property(value) {}
};
```

說明
--

這個簡短的語法和在 ECMAScript 2015 引入 getter 以及 setter 類似。

請看以下程式碼：


```js
var obj = {
  foo: function () {
    /\* code \*/
  },
  bar: function () {
    /\* code \*/
  },
};
```


你可以把它縮減為：


```js
var obj = {
  foo() {
    /\* code \*/
  },
  bar() {
    /\* code \*/
  },
};
```

### 產生器方法

產生器方法（Generator method）也可以透過簡短語法定義之。用的時候：

* 簡短語法的星號（\*）必須放在產生器方法的屬性名前面。也就是說 `* g(){}` 能動但 `g *(){}` 不行；
* 非產生器方法的定義可能不會有 `yield` 關鍵字。也就是說過往的產生器函式 (en-US)動不了、並拋出`SyntaxError` (en-US)。Always use `yield` in conjunction with the asterisk (\*).


```js
// Using a named property
var obj2 = {
  g: function\* () {
    var index = 0;
    while (true) yield index++;
  },
};

// The same object using shorthand syntax
var obj2 = {
  \*g() {
    var index = 0;
    while (true) yield index++;
  },
};

var it = obj2.g();
console.log(it.next().value); // 0
console.log(it.next().value); // 1
```

### Async 方法

Async 方法 也可以透過簡短語法定義。


```js
// Using a named property
var obj3 = {
  f: async function () {
    await some_promise;
  },
};

// The same object using shorthand syntax
var obj3 = {
  async f() {
    await some_promise;
  },
};
```

### Async generator methods

Generator methods can also be async.


```js
var obj4 = {
  f: async function\* () {
    yield 1;
    yield 2;
    yield 3;
  },
};

// The same object using shorthand syntax
var obj4 = {
  async \*f() {
    yield 1;
    yield 2;
    yield 3;
  },
};
```

### Method definitions are not constructable

All method definitions are not constructors and will throw a `TypeError` (en-US) if you try to instantiate them.


```js
var obj = {
  method() {},
};
new obj.method(); // TypeError: obj.method is not a constructor

var obj = {
  \*g() {},
};
new obj.g(); // TypeError: obj.g is not a constructor (changed in ES2016)
```

範例
--

### Simple test case


```js
var obj = {
  a: "foo",
  b() {
    return this.a;
  },
};
console.log(obj.b()); // "foo"
```

### Computed property names

The shorthand syntax also supports computed property names.


```js
var bar = {
  foo0: function () {
    return 0;
  },
  foo1() {
    return 1;
  },
  ["foo" + 2]() {
    return 2;
  },
};

console.log(bar.foo0()); // 0
console.log(bar.foo1()); // 1
console.log(bar.foo2()); // 2
```

規範
--

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

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

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

參見
--

* `get`
* `set`
* Lexical grammar
RangeError: invalid array length
================================

訊息
--
```

RangeError: Array length must be a finite positive integer (Edge)
RangeError: invalid array length (Firefox)
RangeError: Invalid array length (Chrome)
RangeError: Invalid array buffer length (Chrome)
```

錯誤類型
----

`RangeError`哪裡錯了?
-----

一個無效的陣列長度可能發生於以下幾種情形:

* 建立了一個長度為負或大於等於 2^32 的 `Array` 或 `ArrayBuffer`
* 將 `Array.length` 屬性設為負值或大於等於 2^32

為什麼 `Array` 和 `ArrayBuffer` 的長度有限? `Array` 和 `ArrayBuffer` 的屬性以一個 32 位元的非負整數表使，因此僅能儲存 0 到 2^32 - 1 的數值。

If you are creating an `Array`, using the constructor, you probably want to use the literal notation instead, as the first argument is interpreted as the length of the `Array`.

Otherwise, you might want to clamp the length before setting the length property, or using it as argument of the constructor.

示例
--

### 無效的案例


```js
new Array(Math.pow(2, 40));
new Array(-1);
new ArrayBuffer(Math.pow(2, 32)); // 32-bit system
new ArrayBuffer(-1);

const a = [];
a.length = a.length - 1; // set the length property to -1

const b = new Array(Math.pow(2, 32) - 1);
b.length = b.length + 1; // set the length property to 2^32
b.length = 2.5; // set the length property to a floating-point number

const c = new Array(2.5); // pass a floating-point number
```

### 有效的案例


```js
[Math.pow(2, 40)]; // [ 1099511627776 ]
[-1]; // [ -1 ]
new ArrayBuffer(Math.pow(2, 32) - 1);
new ArrayBuffer(Math.pow(2, 33)); // 64-bit systems after Firefox 89
new ArrayBuffer(0);

const a = [];
a.length = Math.max(0, a.length - 1);

const b = new Array(Math.pow(2, 32) - 1);
b.length = Math.min(0xffffffff, b.length + 1);
// 0xffffffff 是 2^32 - 1 的十六進位表示
// 也可以寫成 (-1 >>> 0)

b.length = 3;

const c = new Array(3);
```

參見
--

* `Array`
* `Array.length`
* `ArrayBuffer`
SyntaxError: return not in function
===================================

訊息
--
```

SyntaxError: return not in function
SyntaxError: yield not in function
```

錯誤類型
----

`SyntaxError` (en-US)哪裡錯了？
-----

`return` 或 `yield` (en-US) 宣告在函式以外的地方被呼叫。也許少寫了一個大括號？`return` 與 `yield` 宣告必須要寫在函式裡面，因為它們結束（或暫停並恢復）函式的執行，並且回傳了特定值。

實例
--


```js
var cheer = function(score) {
  if (score === 147)
    return "Maximum!";
  };
  if (score > 100) {
    return "Century!";
  }
}

// SyntaxError: return not in function
```


乍看之下大括號寫對了，但其實在第一個 `if` 的後面，少了一個 `{`。正確的寫法應該是：


```js
var cheer = function (score) {
  if (score === 147) {
    return "Maximum!";
  }
  if (score > 100) {
    return "Century!";
  }
};
```

參見
--

* `return`
* `yield` (en-US)
TypeError: "x" has no properties
================================

訊息
--
```

TypeError: null has no properties
TypeError: undefined has no properties
```

錯誤類型
----

`TypeError` (en-US).

哪裡錯了？
-----

`null` (en-US) 與 `undefined` (en-US) 並沒有可訪問的屬性。

示例
--


```js
null.foo;
// TypeError: null has no properties

undefined.bar;
// TypeError: undefined has no properties
```

參見
--

* `null` (en-US)
* `undefined` (en-US)
SyntaxError: redeclaration of formal parameter "x"
==================================================

訊息
--
```

SyntaxError: redeclaration of formal parameter "x" (Firefox)
SyntaxError: Identifier "x" has already been declared (Chrome)
```

錯誤類型
----

`SyntaxError` (en-US)哪裡錯了？
-----

當相同的變數名作為函式的參數、接著又在函式體（function body）內用了 `let` 重複宣告並指派時出現。在 JavaScript 裡面，不允許在相同的函式、或是作用域區塊（block scope）內重複宣告相同的 `let` 變數。

實例
--

在這裡，「arg」變數的參數被重複宣告。


```js
function f(arg) {
  let arg = "foo";
}

// SyntaxError: redeclaration of formal parameter "arg"
```


If you want to change the value of "arg" in the function body, you can do so, but you do not need to declare the same variable again. In other words: you can omit the `let` keyword. If you want to create a new variable, you need to rename it as conflicts with the function parameter already.


```js
function f(arg) {
  arg = "foo";
}

function f(arg) {
  let bar = "foo";
}
```

相容性註解
-----

* 在 Firefox 49 之前，這個錯誤被歸為 `TypeError` (en-US)。（Firefox bug 1275240）
參見
--

* `let`
* `const`
* `var`
* 在 JavaScript 教學內宣告變數
TypeError: "x" is not a function
================================

訊息
--
```

TypeError: "x" is not a function
```

錯誤類型
----

`TypeError` (en-US).

哪裡錯了？
-----

你想以函式呼叫一個數值，但該數值其實不是函式。程式碼期望你給出函式，但這份期望落空了。

也許打錯了函式的名字？也許呼叫的物件並沒有這個函式？例如說 JavaScript 物件並沒有 `map` 函式，但 JavaScript Array（陣列）物件則有。

許多內建函式都需要回呼（callback）的函式。為了讓下面的方法順利運作，你需要為它們提供函式：

* 如果是 `Array` 或 `TypedArray` (en-US) 物件：
    + `Array.prototype.every()` (en-US)、`Array.prototype.some()` (en-US)、`Array.prototype.forEach()` (en-US)、`Array.prototype.map()`、`Array.prototype.filter()`、`Array.prototype.reduce()`、`Array.prototype.reduceRight()` (en-US)、`Array.prototype.find()`
* 如果是 `Map` 與 `Set` 物件：
    + `Map.prototype.forEach()` (en-US) 與 `Set.prototype.forEach()` (en-US)
實例
--

### 函式的名字打錯了

這種事太常發生了。下例就有個方法打錯：


```js
var x = document.getElementByID("foo");
// TypeError: document.getElementByID is not a function
```


該函式的正確名字為 `getElementById`：


```js
var x = document.getElementById("foo");
```

### 函式呼叫到錯誤的物件

某些方法需要你提供回呼的函式，該函式只能作用於特定物件。以本例而言，我們使用的 `Array.prototype.map()` 就只能作用於 `Array` 物件。


```js
var obj = { a: 13, b: 37, c: 42 };

obj.map(function (num) {
  return num \* 2;
});

// TypeError: obj.map is not a function
```


請改用陣列：


```js
var numbers = [1, 4, 9];

numbers.map(function (num) {
  return num \* 2;
});

// Array [ 2, 8, 18 ]
```

參見
--

* Functions (en-US)
ReferenceError: "x" is not defined
==================================

訊息
--
```

ReferenceError: "x" is not defined
```

錯誤類型
----

`ReferenceError` (en-US).

哪裡錯了？
-----

有個地方參照到不存在的變數了。這個變數需要宣告、或確定在目前腳本、或在 scope (en-US) 裡可用。

**備註：** 如果要使用函式庫（例如 jQuery）的話，請確定在你使用諸如 $ 這樣的函式庫變數前，就已載入完畢。把載入函式庫的 `<script>` 標籤，放在你使用的程式碼之前。

實例
--

### 變數未宣告


```js
foo.substring(1); // ReferenceError: foo is not defined
```


"foo" 變數在任何地方都沒被定義到。它需要字串使 `String.prototype.substring()` (en-US) 得以運作。


```js
var foo = "bar";
foo.substring(1); // "ar"
```

### 作用域錯誤

A variable need to be available in the current context of execution. Variables defined inside a function (en-US) cannot be accessed from anywhere outside the function, because the variable is defined only in the scope of the function


```js
function numbers() {
  var num1 = 2,
    num2 = 3;
  return num1 + num2;
}

console.log(num1); // ReferenceError num1 is not defined.
```


However, a function can access all variables and functions defined inside the scope in which it is defined. In other words, a function defined in the global scope can access all variables defined in the global scope.


```js
var num1 = 2,
  num2 = 3;

function numbers() {
  return num1 + num2;
}

console.log(num1); // 2
```

參閱
--

* Scope (en-US)
* Declaring variables in the JavaScript Guide
* Function scope in the JavaScript Guide
TypeError: "x" is (not) "y"
===========================

錯誤類型
----

`TypeError` (en-US)哪裡錯了？
-----

有一個意想不到的類型。這與 `undefined` (en-US) 或 `null` (en-US) 值經常發生。

另外，某些方法，如 `Object.create()` 或 `Symbol.keyFor()` (en-US) 要求特定類型，即必須提供。

實例
--

### 無效的情況下


```js
// undefined 和 null 的情況下在其上的子方法不起作用
var foo = undefined;
foo.substring(1); // TypeError: foo is undefined

var foo = null;
foo.substring(1); // TypeError: foo is null

// 某些方法可能要求特定類型
var foo = {};
Symbol.keyFor(foo); // TypeError: foo is not a symbol

var foo = "bar";
Object.create(foo); // TypeError: "foo" is not an object or null
```

### 修復問題

為了解決空指針 `undefined` 或 `null` 值，可以使用 typeof 運算符，例如。 operator, for example.


```js
if (typeof foo !== "undefined") {
  // 現在我們知道foo被定義，我們可以繼續進行。
}
```

參見
--

* `undefined` (en-US)
* `null` (en-US)
SyntaxError: missing } after property list
==========================================

訊息
--
```

SyntaxError: missing } after property list
```

錯誤類型
----

`SyntaxError` (en-US)何處出錯?
-----

在物件初始化時，語法錯誤。 實際上可能遺漏一個大括號或是逗號。 例如， 同時檢查大括弧以及逗號是否以正確的順序關閉。 縮排或是有規則的排序代碼是有幫助你找出複雜的代碼錯誤。

範例
--

### 忘記逗號

有時候，在初始化物件時，缺少一個逗號：


```js
var obj = {
  a: 1,
  b: { myProp: 2 }
  c: 3
};
```


Correct would be:


```js
var obj = {
  a: 1,
  b: { myProp: 2 },
  c: 3,
};
```

參見
--

* Object initializer (en-US)
InternalError: too much recursion
=================================

訊息
--
```

InternalError: too much recursion
```

錯誤類型
----

`InternalError` (en-US)哪裡錯了？
-----

一個呼叫自己的函式稱為*遞迴函式*（recursive function）。在某些方面，遞迴和迴圈很像。它們都需要在指定條件（以避免無窮迴圈，或是本例的無窮遞迴）下，重複執行數次相同的程式碼。如果遞迴執行太多次、或成為無窮遞迴的話，JavaScript 就會出現這個錯誤。

實例
--

以下的遞迴函式，會根據終止條件，而運行十次。


```js
function loop(x) {
  if (x >= 10)
    // "x >= 10" 是終止條件
    return;
  // do stuff
  loop(x + 1); // 遞迴呼叫
}
loop(0);
```


如果把終止條件的次數設得太高，函式就不會運作了：


```js
function loop(x) {
  if (x >= 1000000000000) return;
  // do stuff
  loop(x + 1);
}
loop(0);

// InternalError: too much recursion
```

參見
--

* Recursion
* 遞迴函式