recursal/MDN huggingface dataset:
Infinity
========

全局属性 **`Infinity`** 是一个数值，表示无穷大。

尝试一下
----

值
-

与 `Number.POSITIVE_INFINITY` 的数值相同。

| `Infinity` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

描述
--

`Infinity` 是*全局对象*（*global object*）的一个属性，即它是一个全局变量。

`Infinity` 的初始值是 `Number.POSITIVE_INFINITY`。`Infinity`（正无穷大）大于任何值。

该值的意义与数学无穷大略有不同。有关详细信息，请参见 `Number.POSITIVE_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 \*/
console.log(1 / 0); /\* Infinity \*/
```

规范
--

| 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`
* `Number.POSITIVE_INFINITY`
* `Number.isFinite`
ArrayBuffer
===========

**`ArrayBuffer`** 对象用来表示通用的原始二进制数据缓冲区。

它是一个字节数组，通常在其他语言中称为“byte array”。你不能直接操作 `ArrayBuffer` 中的内容；而是要通过类型化数组对象或 `DataView` 对象来操作，它们会将缓冲区中的数据表示为特定的格式，并通过这些格式来读写缓冲区的内容。

`ArrayBuffer()` 构造函数创建一个以字节为单位的给定长度的新 `ArrayBuffer`。你也可以从现有的数据（例如，从 Base64 字符串或者从本地文件）获取数组缓冲区。

`ArrayBuffer` 是一个可转移对象。

描述
--

### 调整 ArrayBuffer 的大小

`ArrayBuffer` 对象可以通过在调用 `ArrayBuffer()` 构造函数时包含 `maxByteLength` 选项来使其大小可变。你可以通过访问其 `resizable` 和 `maxByteLength` 属性来查询 `ArrayBuffer` 的大小是否可变以及其最大值。你可以通过调用 `resize()` 为可变大小的 `ArrayBuffer` 分配一个新的大小。新的字节会被初始化为 0。

这些特性使得调整 `ArrayBuffer` 的大小更加高效——否则，你必须使用新的大小创建一个缓冲副本。这也使得 JavaScript 在这方面与 WebAssembly 相当（Wasm 线性内存可以使用 `WebAssembly.Memory.prototype.grow()` (en-US) 调整大小）。

### 传输 ArrayBuffer

`ArrayBuffer` 对象可以在不同的执行上下文之间传输，就像 Web Worker 或 Service Worker 那样，使用结构化克隆算法。这可以通过在 `Worker.postMessage()` 或 `ServiceWorker.postMessage()` (en-US) 的调用中传入 `ArrayBuffer` 对象作为可转移对象来完成。在纯 JavaScript 中，也可以使用 `transfer()` 或 `transferToFixedLength()` 方法来转移内存的所有权。

当一个 `ArrayBuffer` 对象被传输时，它原来的副本会被*分离（detached）*，这意味着它不再可用。在任何时候，只有一个 `ArrayBuffer` 的副本实际拥有底层内存。分离的缓冲区具有以下行为：

* `byteLength` 变为 0（在缓冲区和关联的类型化数组视图中）。
* 所有实例方法，比如 `resize()` 和 `slice()`，会在调用时抛出 `TypeError`。关联的类型化数组视图的方法也会抛出 `TypeError`。

你可以通过其 `detached` 属性来检查 `ArrayBuffer` 是否已分离。

构造函数
----

`ArrayBuffer()`

创建一个新的 `ArrayBuffer` 对象。

静态属性
----

`ArrayBuffer[@@species]`

用于创建派生对象的构造函数。

静态方法
----

`ArrayBuffer.isView()`

如果 `arg` 是 ArrayBuffer 视图之一，则返回 `true`，例如类型化数组对象或者 `DataView`。否则返回 `false`。

实例属性
----

这些属性在 `ArrayBuffer.prototype` 上定义，并由所有 `ArrayBuffer` 实例共享。

`ArrayBuffer.prototype.byteLength`

`ArrayBuffer` 的大小，以字节为单位。它在构造时确定，并且只有在 `ArrayBuffer` 可调整大小的情况下才能通过 `ArrayBuffer.prototype.resize()` 方法进行改变。

`ArrayBuffer.prototype.constructor`

创建实例对象的构造函数。对于 `ArrayBuffer` 实例，初始值为 `ArrayBuffer` 构造函数。

`ArrayBuffer.prototype.detached` 
实验性

只读。如果 `ArrayBuffer` 已分离（传输），则返回 `true`，否则返回 `false`。

`ArrayBuffer.prototype.maxByteLength`

只读，`ArrayBuffer` 可以调整到的最大字节长度。它在构造时确定，并且无法更改。

`ArrayBuffer.prototype.resizable`

只读。如果 `ArrayBuffer` 可调整大小，则返回 `true`，否则返回 `false`。

`ArrayBuffer.prototype[@@toStringTag]`

`@@toStringTag` 属性的初始值是字符串 `"ArrayBuffer"`。它用于 `Object.prototype.toString()`。

实例方法
----

`ArrayBuffer.prototype.resize()`

将 `ArrayBuffer` 调整为指定大小，以字节为单位。

`ArrayBuffer.prototype.slice()`

返回一个新的 `ArrayBuffer` 对象，其内容是从 `begin`（包含）到 `end`（不包含）的 `ArrayBuffer` 的字节内容的副本。如果 `begin` 或 `end` 为负数，则它将从数组的末尾开始计算索引，而非从数组的开头。

`ArrayBuffer.prototype.transfer()` 
实验性

创建一个新的 `ArrayBuffer` 对象，其内容是与此缓冲区相同的字节内容，然后分离此缓冲区。

`ArrayBuffer.prototype.transferToFixedLength()` 
实验性

创建一个新的不可调整大小的 `ArrayBuffer` 对象，其内容与此缓冲区相同，然后分离此缓冲区。

示例
--

### 创建 ArrayBuffer

下面的例子创建了一个 8 字节的缓冲区，并使用 `Int32Array` 视图引用它。


```js
const buffer = new ArrayBuffer(8);
const view = new Int32Array(buffer);
```

规范
--

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

浏览器兼容性
------

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

参见
--

* `core-js` 中 `ArrayBuffer` 的 polyfill
* JavaScript 类型化数组
* `SharedArrayBuffer`
* RangeError: invalid array length
RangeError
==========

**`RangeError`** 对象表示一个特定值不在所允许的范围或者集合中的错误。

描述
--

试图将一个值作为参数传递给一个允许的范围不包含该值的函数会引发 `RangeError`。

在以下的情况中，可能会遇到这个问题：

* 将不允许的字符串值传递给 `String.prototype.normalize()`，或
* 尝试使用 `Array` 构造函数创建一个具有不合法的长度的字符串，或
* 传递错误值到数值计算方法（`Number.toExponential()`、`Number.toFixed()` 或 `Number.toPrecision()`）。

`RangeError` 是一个可序列化对象，所以可以使用 `structuredClone()` 对它进行克隆，也可以使用 `postMessage()` 在 Worker 之间拷贝它。

构造函数
----

`RangeError()` (en-US)

创建一个新的 `RangeError` 对象。

实例属性
----

`Error.prototype.message`

错误消息。继承自 `Error`。

`Error.prototype.name`

错误名称。继承自 `Error`。

`Error.prototype.cause`

表示导致当前错误被抛出的原因。继承自 `Error`。

`Error.prototype.fileName` 
非标准

引发此错误的文件的路径。继承自 `Error`。

`Error.prototype.lineNumber` 
非标准

引发此错误的代码所在的文件的行号。继承自 `Error`。

`Error.prototype.columnNumber` 
非标准

引发此错误的代码在文件中所在行的列号。继承自 `Error`。

`Error.prototype.stack` 
非标准

堆栈跟踪。继承自 `Error`。

示例
--

### 使用 RangeError（对于数值）


```js
function check(n) {
  if (!(n >= -500 && n <= 500)) {
    throw new RangeError("The argument must be between -500 and 500.");
  }
}

try {
  check(2000);
} catch (error) {
  if (error instanceof RangeError) {
    // 处理错误
  }
}
```

### 使用 RangeError（对于其他的值）


```js
function check(value) {
  if (!["apple", "banana", "carrot"].includes(value)) {
    throw new RangeError(
      'The argument must be an "apple", "banana", or "carrot".',
    );
  }
}

try {
  check("cabbage");
} catch (error) {
  if (error instanceof RangeError) {
    // 处理错误
  }
}
```

规范
--

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

浏览器兼容性
------

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

参见
--

* `Error`
* `Array`
* `Number.prototype.toExponential()`
* `Number.prototype.toFixed()`
* `Number.prototype.toPrecision()`
* `String.prototype.normalize()`
Atomics
=======

**`Atomics`** 命名空间对象包含对 `SharedArrayBuffer` 和 `ArrayBuffer` 对象执行原子操作的静态方法。

描述
--

与一般的全局对象不同，`Atomics` 不是构造函数。因此你不能将其与 new 运算符一起使用或将 `Atomics` 对象作为一个函数来进行调用。`Atomics` 的所有属性和方法都是静态的（与 `Math` 对象一样）。

### 原子操作

当内存被共享时，多个的线程能够读写内存上的同一数据。原子操作会确保正在读或写的数据的值是符合预期的，即下一个原子操作一定会在上一个原子操作结束后才会开始，其操作不会被中断。

### 等待和通知

`wait()` 和 `notify()` 方法采用的是 Linux 上的 futex 模型（“快速用户空间互斥体”），可以让进程一直等待直到某个特定的条件为真，主要用于实现阻塞。

静态属性
----

`Atomics[@@toStringTag]`

`@@toStringTag` 属性的初始值是字符串 `"Atomics"`。这个属性在 `Object.prototype.toString()` 中使用。

静态方法
----

`Atomics.add()`

将给定的值与数组上指定位置的元素相加，并返回相加前该元素的值。

`Atomics.and()`

将指定位置上的数组元素与给定的值相与，并返回与操作前该元素的值。

`Atomics.compareExchange()`

如果数组中指定的元素与给定的值相等，则将其更新为新的值，并返回该元素原先的值。

`Atomics.exchange()`

将数组中指定的元素更新为给定的值，并返回该元素更新前的值。

`Atomics.isLockFree()`

一个优化原语，可用于确定是使用锁还是原子操作。如果给定元素大小的数组上的原子操作将使用硬件原子操作来实现（而不是锁），则返回`true`。仅供专家使用。

`Atomics.load()`

返回数组中指定元素的值。

`Atomics.notify()`

通知正在等待数组指定索引的代理。返回收到通知的代理数量。

`Atomics.or()`

将指定位置上的数组元素与给定的值相或，并返回或操作前该元素的值。

`Atomics.store()`

将值储存到数组的指定位置，并返回该值。

`Atomics.sub()`

将指定位置上的数组元素与给定的值相减，并返回相减前该元素的值。

`Atomics.wait()`

检测数组中某个指定位置上的值是否仍然是给定值，是则保持挂起直到被唤醒或超时。返回值为 `"ok"`、`"not-equal"` 或 `"time-out"`。调用时，如果当前代理不允许阻塞，则会抛出异常（大多数浏览器都不允许在主线程中调用 `wait()`）。

`Atomics.waitAsync()`

在共享内存位置上异步等待（即没有阻塞，与 `Atomics.wait` 不同）并返回一个 `Promise`。

`Atomics.xor()`

将指定位置上的数组元素与给定的值相异或，并返回异或操作前该元素的值。

示例
--

### 使用 Atomics


```js
const sab = new SharedArrayBuffer(1024);
const ta = new Uint8Array(sab);

ta[0]; // 0
ta[0] = 5; // 5

Atomics.add(ta, 0, 12); // 5
Atomics.load(ta, 0); // 17

Atomics.and(ta, 0, 1); // 17
Atomics.load(ta, 0); // 1

Atomics.compareExchange(ta, 0, 5, 12); // 1
Atomics.load(ta, 0); // 1

Atomics.exchange(ta, 0, 12); // 1
Atomics.load(ta, 0); // 12

Atomics.isLockFree(1); // true
Atomics.isLockFree(2); // true
Atomics.isLockFree(3); // false
Atomics.isLockFree(4); // true

Atomics.or(ta, 0, 1); // 12
Atomics.load(ta, 0); // 13

Atomics.store(ta, 0, 12); // 12

Atomics.sub(ta, 0, 2); // 12
Atomics.load(ta, 0); // 10

Atomics.xor(ta, 0, 1); // 10
Atomics.load(ta, 0); // 11
```

### 等待和通知

给定一个共享的 `Int32Array`：


```js
const sab = new SharedArrayBuffer(1024);
const int32 = new Int32Array(sab);
```


如果位置 0 上的值为 0，则读取线程将保持休眠且代码不会继续执行。但是，一旦写入线程储存了一个新的值，则写入线程将通知它并返回新的值（123）。


```js
Atomics.wait(int32, 0, 0);
console.log(int32[0]); // 123
```


写入线程存储一个新值并在写入完成时通知一次等待线程该位置被写入：


```js
console.log(int32[0]); // 0;
Atomics.store(int32, 0, 123);
Atomics.notify(int32, 0, 1);
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-atomics-object |

浏览器兼容性
------

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

参见
--

* `ArrayBuffer`
* JavaScript 类型化数组
* Web Worker
* Shared Memory——一个简短的教程，在 TC39 ecmascript-sharedmem 提案中
* JavaScript 新并行语法的初体验 在 hacks.mozilla.org 上（2016）
isNaN()
=======

**`isNaN()`** 函数用来确定一个值是否为 `NaN`，若有必要，则首先将值转换为数字。由于 `isNaN()` 函数内部的强制类型转换可能令人迷惑，因此你可能更想要使用 `Number.isNaN()`。

尝试一下
----

语法
--


```js
isNaN(value)
```

### 参数

`value`

要被检测的值。

### 返回值

如果给定值在被转换为数字后为 `NaN` 则返回值为 `true`；否则为 `false`。

描述
--

`isNaN()` 是全局对象的一个函数属性。

对于数字值，`isNaN()` 检测该值是否为 `NaN` 值。当 `isNaN()` 函数的参数不是数字类型时，其会首先被转换为数字，然后将其结果值与 `NaN` 进行比较。

`isNaN()` 对于非数字参数的行为可能会令人困惑！例如，空字符串被强制转换为 0，布尔值被强制转换为 0 或 1；直观上，两者均“不是数字”，仅因它们的运算结果不是 `NaN`，而使得 `isNaN()` 返回 `false`。因此，`isNaN()` 既不回答“输入是否为浮点数值 `NaN`”，也不回答“输入是否为数字”这两个问题。

`Number.isNaN()` 是检测一个值是否为数字值 `NaN` 的更可靠的方法。或者，也可以使用表达式 `x !== x`，这两种方法都不会产生全局 `isNaN()` 不可靠的误判。要检测一个值是否为数字，请使用 `typeof x === "number"`。

`isNaN()` 函数回答的问题是“在数字上下文中，输入是否在功能上与 `NaN` 等价”。如果 `isNaN(x)` 返回 `false`，则可以在算术表达式中使用 `x`，就好像它是一个有效的数字，而不是 `NaN`。如果 `isNaN(x)` 返回 `true`，则 `x` 将被强制转换为 `NaN`，并使大多数算术表达式返回 `NaN`（因为 `NaN` 会传播）。例如，可以使用这种方法来测试函数的参数是否可以进行算术处理（像数字一样使用），并通过抛出错误、提供默认值等来处理不是数字的值。这样，就可以拥有一个可以利用 JavaScript 提供的全部灵活性的函数，该函数可以根据上下文隐式地转换值。

**备注：** `+` 运算符既执行数字加法又执行字符串连接。因此，即使 `isNaN()` 对两个操作数都返回 `false`，`+` 运算符仍可能因为它不是被用作算术运算符而返回字符串。例如，`isNaN("1")` 返回 `false`，而 `"1" + 1` 返回 `"11"`。要确保你正在使用数字，请将值强制转换为数字并使用 `Number.isNaN()` 来测试结果。

示例
--

注意 `isNaN()` 为什么会对一些既不是数字也不是 `NaN` 的值返回 `true`：


```js
isNaN(NaN); // true
isNaN(undefined); // true
isNaN({}); // true

isNaN(true); // false
isNaN(null); // false
isNaN(37); // false

// 字符串
isNaN("37"); // false：可以被转换成数字 37，不是 NaN
isNaN("37.37"); // false：可以被转换成数字 37.37，不是 NaN
isNaN("37,5"); // true
isNaN("123ABC"); // true：Number("123ABC") 的结果是 NaN
isNaN(""); // false：空字符串被转换成 0，不是 NaN
isNaN(" "); // false：由空格组成的字符串被转换成 0，不是 NaN

// 日期
isNaN(new Date()); // false；Date 对象可以转换为数字（时间戳）
isNaN(new Date().toString()); // true；Date 对象的字符串表示形式不能解析为数字
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-isnan-number |

浏览器兼容性
------

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

参见
--

* `NaN`
* `Number.isNaN()`
TypeError
=========

**`TypeError`**（类型错误）对象通常（但并不只是）用来表示值的类型非预期类型时发生的错误。

以下情况会抛出 `TypeError`：

* 传递给运算符的操作数或传递给函数的参数与预期的类型不兼容；或
* 尝试修改无法更改的值；或
* 尝试以不适当的方法使用一个值。

`TypeError` 是一个可序列化对象，所以可以使用 `structuredClone()` 对它进行克隆，也可以使用 `postMessage()` 在 Worker 之间拷贝它。

构造函数
----

`TypeError()` (en-US)

创建一个新的 `TypeError` 对象。

实例属性
----

`Error.prototype.message`

错误消息。继承自 `Error`。

`Error.prototype.name`

错误名称。继承自 `Error`。

`Error.prototype.cause`

表示导致当前错误被抛出的原因。继承自 `Error`。

`Error.prototype.fileName` 
非标准

引发此错误的文件的路径。继承自 `Error`。

`Error.prototype.lineNumber` 
非标准

引发此错误的代码所在的文件的行号。继承自 `Error`。

`Error.prototype.columnNumber` 
非标准

引发此错误的代码在文件中所在行的列号。继承自 `Error`。

`Error.prototype.stack` 
非标准

堆栈跟踪。继承自 `Error`。

示例
--

### 捕获类型错误


```js
try {
  null.f();
} catch (e) {
  console.log(e instanceof TypeError); // true
  console.log(e.message); // "null has no properties"
  console.log(e.name); // "TypeError"
  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"
}
```

### 创建一个类型错误


```js
try {
  throw new TypeError("Hello", "someFile.js", 10);
} catch (e) {
  console.log(e instanceof TypeError); // true
  console.log(e.message); // "Hello"
  console.log(e.name); // "TypeError"
  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-typeerror |

浏览器兼容性
------

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

参见
--

* `Error`
Function
========

**`Function`** 对象提供了用于处理函数的方法。在 JavaScript 中，每个函数实际上都是一个 `Function` 对象。

构造函数
----

`Function()`

创建一个新的 `Function` 对象。直接调用此构造函数可以动态创建函数，但会遇到和 `eval()` 类似的的安全问题和（相对较小的）性能问题。然而，与 `eval()` 不同的是，`Function` 构造函数创建的函数只能在全局作用域中运行。

实例属性
----

以下属性定义在 `Function.prototype` 上，并且被所有 `Function` 实例共享。

`Function.prototype.arguments` 
已弃用

非标准

表示传递给该函数的参数。对于严格模式、箭头函数、异步函数和生成器函数，访问 `arguments` 属性会抛出 `TypeError` 异常。请改为在函数闭包内使用 `arguments` 对象。

`Function.prototype.caller` 
已弃用

非标准

表示调用该函数的函数。对于严格模式、箭头函数、异步函数和生成器函数，访问 `caller` 属性会抛出 `TypeError` 异常。

`Function.prototype.constructor`

创建实例对象的构造函数。对于 `Function` 实例来说，初始值是 `Function` 构造函数。

以下属性是每个 `Function` 实例的自有属性。

`displayName` 
非标准
 可选

函数的显示名称。

`length`

指定函数期望的参数个数。

`name`

函数的名称。

`prototype`

在使用 `function` 作为构造函数与 `new` 运算符一起使用时，用作新对象的原型。

实例方法
----

`Function.prototype.apply()`

使用给定的 `this` 值和可选的参数数组（或类数组对象）作为参数来调用一个函数。

`Function.prototype.bind()`

创建一个新的函数，在调用时，其 `this` 关键字被设置为提供的值，可选地在调用新函数时在提供的参数之前加上一系列给定的参数。

`Function.prototype.call()`

使用给定的 `this` 值和可选参数调用一个函数。

`Function.prototype.toString()`

返回表示函数源代码的字符串。重写了 `Object.prototype.toString` 方法。

`Function.prototype[@@hasInstance]()`

指定确定构造函数是否将对象识别为其实例的默认过程。由 `instanceof` 运算符调用。

示例
--

### Function 构造函数与函数声明之间的不同

由 `Function` 构造函数创建的函数不会创建当前环境的闭包，它们总是被创建于全局环境，因此在运行时它们只能访问全局变量和自己的局部变量，不能访问它们被 `Function` 构造函数创建时所在的作用域的变量。这一点与使用 `eval()` 执行创建函数的代码不同。


```js
// 使用 `var` 创建一个全局属性
var x = 10;

function createFunction1() {
  const x = 20;
  return new Function("return x;"); // 这个 `x` 指的是全局 `x`
}

function createFunction2() {
  const x = 20;
  function f() {
    return x; // 这个 `x` 指的是上面的局部 `x`
  }
  return f;
}

const f1 = createFunction1();
console.log(f1()); // 10
const f2 = createFunction2();
console.log(f2()); // 20
```


虽然这段代码可以在浏览器中正常运行，但在 Node.js 中 `f1()` 会产生一个“找不到变量 `x`”的 `ReferenceError`。这是因为在 Node 中顶级作用域不是全局作用域，而 `x` 其实是在当前模块的作用域之中。

规范
--

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

浏览器兼容性
------

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

参见
--

* 函数声明
* 函数表达式
* `AsyncFunction`
* `AsyncGeneratorFunction`
* `GeneratorFunction`
* 函数
JSON
====

**`JSON`** 对象包含两个方法：用于解析 JavaScript Object Notation（JSON）的 `parse()` 方法，以及将对象/值转换为 JSON 字符串的 `stringify()` 方法。除了这两个方法，JSON 这个对象本身并没有其他作用，也不能被调用或者作为构造函数调用。

描述
--

### JavaScript Object Notation

**JSON** 是一种语法，用来序列化对象、数组、数值、字符串、布尔值和 `null` 。它基于 JavaScript 语法，但与之不同：**JavaScript 不是 JSON，JSON 也不是 JavaScript**。参考 JSON：并不是 JavaScript 的子集。

JavaScript 与 JSON 的区别| JavaScript 类型 | JSON 的不同点 |
| --- | --- |
| 对象和数组 | 属性名称必须是双引号括起来的字符串；最后一个属性后不能有逗号。 |
| 数值 | 禁止出现前导零（JSON.stringify 方法自动忽略前导零，而在 JSON.parse 方法中将会抛出 SyntaxError）；如果有小数点，则后面至少跟着一位数字。 |
| 字符串 | 只有有限的一些字符可能会被转义；禁止某些控制字符；Unicode 行分隔符（U+2028）和段分隔符（U+2029）被允许 ; 字符串必须用双引号括起来。请参考下面的示例，可以看到 `JSON.parse()` 能够正常解析，但将其当作 JavaScript 解析时会抛出 `SyntaxError` 错误：

```js
let code = '"\u2028\u2029"';
JSON.parse(code); // 正常
eval(code); // 错误
```

 |

完整的 JSON 语法定义如下：
```

JSON = null
    or true or false
    or JSONNumber
    or JSONString
    or JSONObject
    or JSONArray

JSONNumber = - PositiveNumber
          or PositiveNumber
PositiveNumber = DecimalNumber
              or DecimalNumber . Digits
              or DecimalNumber . Digits ExponentPart
              or DecimalNumber ExponentPart
DecimalNumber = 0
             or OneToNine Digits
ExponentPart = e Exponent
            or E Exponent
Exponent = Digits
        or + Digits
        or - Digits
Digits = Digit
      or Digits Digit
Digit = 0 through 9
OneToNine = 1 through 9

JSONString = ""
          or " StringCharacters "
StringCharacters = StringCharacter
                or StringCharacters StringCharacter
StringCharacter = any character
                  except " or \ or U+0000 through U+001F
               or EscapeSequence
EscapeSequence = \" or \/ or \\ or \b or \f or \n or \r or \t
              or \u HexDigit HexDigit HexDigit HexDigit
HexDigit = 0 through 9
        or A through F
        or a through f

JSONObject = { }
          or { Members }
Members = JSONString : JSON
       or Members , JSONString : JSON

JSONArray = [ ]
         or [ ArrayElements ]
ArrayElements = JSON
             or ArrayElements , JSON
```


在 `JSONNumber`（数字内部不允许包含空格）或 `JSONString`（字符串内部的空格被解释为相应的字符，否则就有问题了）之外的任何位置可以有多余的空白字符。JSON 只支持这些空白字符：制表符（U+0009），回车（U+000D），换行（U+000A）以及空格（U+0020）。

方法
--

`JSON.parse()`

解析 JSON 字符串并返回对应的值，可以额外传入一个转换函数，用来将生成的值和其属性，在返回之前进行某些修改。

`JSON.stringify()`

返回与指定值对应的 JSON 字符串，可以通过额外的参数，控制仅包含某些属性，或者以自定义方法来替换某些 key 对应的属性值。

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-json-object |

浏览器兼容性
------

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

参见
--

* `Date.prototype.toJSON()`
ReferenceError
==============

**`ReferenceError`**（引用错误）对象代表当一个不存在（或尚未初始化）的变量被引用时发生的错误。

`ReferenceError` 是一个可序列化对象，所以可以使用 `structuredClone()` 对它进行克隆，也可以使用 `postMessage()` 在 Worker 之间拷贝它。

构造函数
----

`ReferenceError()` (en-US)

创建一个新的 `ReferenceError` 对象。

实例属性
----

`Error.prototype.message`

错误消息。继承自 `Error`。

`Error.prototype.name`

错误名称。继承自 `Error`。

`Error.prototype.cause`

表示导致当前错误被抛出的原因。继承自 `Error`。

`Error.prototype.fileName` 
非标准

引发此错误的文件的路径。继承自 `Error`。

`Error.prototype.lineNumber` 
非标准

引发此错误的代码所在的文件的行号。继承自 `Error`。

`Error.prototype.columnNumber` 
非标准

引发此错误的代码在文件中所在行的列号。继承自 `Error`。

`Error.prototype.stack` 
非标准

堆栈跟踪。继承自 `Error`。

示例
--

### 捕获一个 ReferenceError


```js
try {
  let a = undefinedVariable;
} catch (e) {
  console.log(e instanceof ReferenceError); // true
  console.log(e.message); // "undefinedVariable is not defined"
  console.log(e.name); // "ReferenceError"
  console.log(e.fileName); // "Scratchpad/1"
  console.log(e.lineNumber); // 2
  console.log(e.columnNumber); // 6
  console.log(e.stack); // "@Scratchpad/2:2:7\n"
}
```

### 创建一个 ReferenceError


```js
try {
  throw new ReferenceError("Hello", "someFile.js", 10);
} catch (e) {
  console.log(e instanceof ReferenceError); // true
  console.log(e.message); // "Hello"
  console.log(e.name); // "ReferenceError"
  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-referenceerror |

浏览器兼容性
------

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

参见
--

* `Error`
globalThis
==========

全局属性 `globalThis` 包含全局的 `this` 值，类似于全局对象（global object）。

尝试一下
----

| `globalThis` 的属性特性 |
| --- |
| 可写 | 是 |
| 可枚举 | 否 |
| 可配置 | 是 |

语法
--
```

globalThis
```

描述
--

在以前，从不同的 JavaScript 环境中获取全局对象需要不同的语句。在 Web 中，可以通过 `window`、`self` 或者 `frames` 取到全局对象，但是在 Web Workers 中，只有 `self` 可以。在 Node.js 中，它们都无法获取，必须使用 `global`。

在松散模式下，可以在函数中返回 `this` 来获取全局对象，但是在严格模式和模块环境下，`this` 会返回 `undefined`。你也可以使用 `Function('return this')()`，但那些禁用`eval()`的环境，如在浏览器中的CSP，不允许这样使用`Function`。

`globalThis` 提供了一个标准的方式来获取不同环境下的全局 `this` 对象（也就是全局对象自身）。不像 `window` 或者 `self` 这些属性，它确保可以在有无窗口的各种环境下正常工作。所以，你可以安心的使用 `globalThis`，不必担心它的运行环境。为便于记忆，你只需要记住，全局作用域中的 `this` 就是 `globalThis`。

### HTML 与 WindowProxy

在很多引擎中， `globalThis` 被认为是真实的全局对象的引用，但是在浏览器中，由于 iframe 以及跨窗口安全性的考虑，它实际引用的是真实全局对象（不可以被直接访问）的 `Proxy` 代理。在通常的应用中，很少会涉及到代理与对象本身的区别，但是也需要加以注意。

### 命名

并没有采用一些更常见的命名方式，如 `self` 和 `global`，这是为了避免影响现存代码的兼容性。更多相关信息可以查看 language proposal's "naming" document 。

示例
--

在 `globalThis` 之前，获取某个全局对象的唯一方式就是 `Function('return this')()`，但是这在某些情况下会违反 CSP 规则，所以，es6-shim 使用了类似如下的方式：


```js
var getGlobal = function () {
  if (typeof self !== "undefined") {
    return self;
  }
  if (typeof window !== "undefined") {
    return window;
  }
  if (typeof global !== "undefined") {
    return global;
  }
  throw new Error("unable to locate global object");
};

var globals = getGlobal();

if (typeof globals.setTimeout !== "function") {
  // 此环境中没有 setTimeout 方法！
}
```


但是有了 `globalThis` 之后，只需要：


```js
if (typeof globalThis.setTimeout !== "function") {
  // 此环境中没有 setTimeout 方法！
}
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-globalthis |

浏览器兼容性
------

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

全局属性 **`NaN`** 是一个表示非数字的值。

| `NaN` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

尝试一下
----

描述
--

`NaN`是*全局对象*的一个属性。换句话说，它是全局作用域中的一个变量。

`NaN` 的初始值不是数字——与 `Number.NaN` 的值相同。在现代浏览器中，`NaN` 是一个不可配置、不可写的属性。即使不是这样，也要避免重写它。在程序中很少使用 `NaN`。

有五种不同类型的操作返回 `NaN`：

* 失败的数字转换（例如，显式转换，如 `parseInt("blabla")`、`Number(undefined)`，或隐式转换，如 `Math.abs(undefined)`）
* 计算结果不是实数的数学运算（例如，`Math.sqrt(-1)`）
* 不定式（例如，`0 * Infinity`、`1 ** Infinity`、`Infinity / Infinity`、`Infinity - Infinity`）
* 一个操作数被强制转换为 `NaN` 的方法或表达式（例如，`7 ** NaN`、`7 * "blabla"`）——这意味着 `NaN` 具有传染性
* 将无效值表示为数字的其他情况（例如，无效的 Date `new Date("blabla").getTime()`、`"".charCodeAt(1)`）

`NaN` 及其行为不是 JavaScript 发明的。它在浮点运算中的语义（包括 `NaN !== NaN`）是由 IEEE 754 指定的。`NaN` 的行为包括：

* 如果 `NaN` 涉及数学运算（但不涉及位运算），结果通常也是 `NaN`。（参见下面的反例。）
* 当 `NaN` 是任何关系比较（`>`, `<`, `>=`, `<=`）的操作数之一时，结果总是 `false`。
* `NaN` 不等于（通过 `==`、`!=`、`===` 和 `!==`）任何其他值——包括与另一个 `NaN` 值。

`NaN` 也是 JavaScript 中的假值之一。

示例
--

### 针对 NaN 的测试

要判断一个值是否为 `NaN`，可以使用 `Number.isNaN()` 或 `isNaN()` 来最清楚地确定一个值是否为 `NaN`——或者，因为 `NaN` 是唯一与自身不相等的值，所以你可以执行类似 `x !== x` 这样的自我比较。


```js
NaN === NaN; // false
Number.NaN === NaN; // false
isNaN(NaN); // true
isNaN(Number.NaN); // true
Number.isNaN(NaN); // true

function valueIsNaN(v) {
  return v !== v;
}
valueIsNaN(1); // false
valueIsNaN(NaN); // true
valueIsNaN(Number.NaN); // true
```


但是，请注意 `isNaN()` 和 `Number.isNaN()` 之间的区别：如果当前值是 `NaN`，或者将其强制转换为数字后将是 `NaN`，则前者将返回 `true`。而后者仅当值当前为 `NaN` 时才为 `true`：


```js
isNaN("hello world"); // true
Number.isNaN("hello world"); // false
```


出于同样的原因，使用 BigInt 值时 `isNaN()` 会抛出错误，而 `Number.isNaN()` 不会：


```js
isNaN(1n); // TypeError: Conversion from 'BigInt' to 'number' is not allowed.
Number.isNaN(1n); // false
```


此外，一些数组方法不能找到 `NaN`，而另一些可以。也就是说，查找索引的（`indexOf()`、`lastIndexOf()`）不能找到 `NaN`，而查找值的（`includes()`）可以：


```js
const arr = [2, 4, NaN, 12];
arr.indexOf(NaN); // -1
arr.includes(NaN); // true

// Methods accepting a properly defined predicate can always find NaN
arr.findIndex((n) => Number.isNaN(n)); // 2
```


有关 `NaN` 及其比较的更多信息，请参阅相等性判断。

### 明显不同的 NaN 值

这是 `NaN` 与自身不平等的动机。可以用不同的二进制表示生成两个都是 `NaN` 的浮点数，因为在 IEEE 754 编码中，任何指数为 `0x7ff` 且尾数非零的浮点数都是 `NaN`。在 JavaScript 中，你可以使用类型化数组来进行位操作。


```js
const f2b = (x) => new Uint8Array(new Float64Array([x]).buffer);
const b2f = (x) => new Float64Array(x.buffer)[0];
// Get a byte representation of NaN
const n = f2b(NaN);
// Change the first bit, which is the sign bit and doesn't matter for NaN
n[0] = 1;
const nan2 = b2f(n);
console.log(nan2); // NaN
console.log(Object.is(nan2, NaN)); // true
console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
console.log(f2b(nan2)); // Uint8Array(8) [1, 0, 0, 0, 0, 0, 248, 127]
```

### 默默逃离 NaN

`NaN` 通过数学运算进行传播，因此通常在计算结束时测试 `NaN` 一次就足以检测错误条件。`NaN` 被静默转义的唯一情况是使用指数为 `0` 求幂时，它立即返回 `1` 而不测试基数的值。


```js
NaN \*\* 0 === 1; // true
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-value-properties-of-the-global-object-nan |

浏览器兼容性
------

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

参见
--

* `Number.NaN`
* `Number.isNaN()`
* `isNaN()`