RegExp(正则表达式) - JavaScript

RegExp(正则表达式)
=============

**`RegExp`** 对象用于将文本与一个模式匹配。

有关正则表达式的介绍，请阅读 JavaScript 指南中的正则表达式章节。

描述
--

### 字面量和构造函数

有两种方法可以创建一个 `RegExp` 对象：一种是字面量，另一种是构造函数。

字面量

由斜杠 (/) 包围而不是引号包围。

构造函数的字符串参数

由引号而不是斜杠包围。

以下三种表达式都会创建相同的正则表达式：

```js
/ab+c/i; //字面量形式
new RegExp("ab+c", "i"); // 首个参数为字符串模式的构造函数
new RegExp(/ab+c/, "i"); // 首个参数为常规字面量的构造函数
```

当表达式被赋值时，字面量形式提供正则表达式的编译（compilation）状态，当正则表达式保持为常量时使用字面量。例如当你在循环中使用字面量构造一个正则表达式时，正则表达式不会在每一次迭代中都被重新编译（recompiled）。

而正则表达式对象的构造函数，如 `new RegExp('ab+c')` 提供了正则表达式运行时编译（runtime compilation）。如果你知道正则表达式模式将会改变，或者你事先不知道什么模式，而是从另一个来源获取，如用户输入，这些情况都可以使用构造函数。

### 构造函数中的标志参数 (flags)

从 ECMAScript 6 开始，当第一个参数为正则表达式而第二个标志参数存在时，`new RegExp(/ab+c/, 'i')` 不再抛出 `TypeError`（`"从另一个 RegExp 构造一个 RegExp 时无法提供标志"`）的异常，取而代之，将使用这些参数创建一个新的正则表达式。

当使用构造函数创造正则对象时，需要常规的字符转义规则（在前面加反斜杠 `\`）。

比如，以下是等价的：

```js
var re = new RegExp("\\w+");
var re = /\w+/;
```

### Perl-like RegExp 属性

请注意，`RegExp`属性有长名称和短名称（类似 Perl）。两个名称总是引用同一个值。（Perl 是 JavaScript 为其正则表达式建模的编程语言）。另请参见不推荐使用的 RegExp 属性。

构造函数
----

`RegExp()`

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

静态属性
----

`get RegExp[@@species]`

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

`RegExp.lastIndex`

该索引表示从哪里开始下一个匹配

实例属性
----

`RegExp.prototype.flags`

含有 `RegExp` 对象 flags 的字符串。

`RegExp.prototype.dotAll`

`.` 是否要匹配新行（newlines）。

`RegExp.prototype.global`

针对字符串中所有可能的匹配项测试正则表达式，还是仅针对第一个匹配项。

`RegExp.prototype.ignoreCase`

匹配文本的时候是否忽略大小写。

`RegExp.prototype.multiline`

是否进行多行搜索。

`RegExp.prototype.source`

正则表达式的文本。

`RegExp.prototype.sticky`

搜索是否是 sticky。

`RegExp.prototype.unicode`

Unicode 功能是否开启。

实例方法
----

`RegExp.prototype.compile()`

运行脚本的期间（重新）编译正则表达式。

`RegExp.prototype.exec()`

在该字符串中执行匹配项的搜索。

`RegExp.prototype.test()`

该正则在字符串里是否有匹配。

`RegExp.prototype[@@match]()`

对给定字符串执行匹配并返回匹配结果。

`RegExp.prototype[@@matchAll]()`

对给定字符串执行匹配，返回所有匹配结果。

`RegExp.prototype[@@replace]()`

给定新的子串，替换所有匹配结果。

`RegExp.prototype[@@search]()`

在给定字符串中搜索匹配项，并返回在字符串中找到字符索引。

`RegExp.prototype[@@split]()`

通过将给定字符串拆分为子字符串，并返回字符串形成的数组。

`RegExp.prototype.toString()`

返回表示指定对象的字符串。重写`Object.prototype.toString()`方法。

示例
--

### 使用正则改变数据结构

下例使用 `String` 的 `replace()` 方法去匹配姓名 *first last* 输出新的格式 *last*, *first*。

在替换的文本中，脚本中使用 `$1` 和 `$2` 指明括号里先前的匹配。

```js
let re = /(\w+)\s(\w+)/;
let str = "John Smith";
let newstr = str.replace(re, "$2, $1");
console.log(newstr);
```

这将显示 "Smith, John".

### 使用正则来划分带有多种行结束符和换行符的文本

对于不同的平台（Unix，Windows 等等），其默认的行结束符是不一样的。而下面的划分方式适用于所有平台。
```

let text = 'Some text\nAnd some more\r\nAnd yet\rThis is the end'
let lines = text.split(/\r\n|\r|\n/)
console.log(lines) // logs [ 'Some text', 'And some more', 'And yet', 'This is the end' ]
```

注意：在正则表达式中，以竖线分割的子模式的顺序会影响匹配结果。

### 在多行文本中使用正则表达式

```js
let s = "Please yes\nmake my day!";

s.match(/yes.\*day/);
// Returns null

s.match(/yes[^]\*day/);
// Returns 'yes\nmake my day'
```

### 使用带有 sticky 标志的正则表达式

带有`sticky`标志的正则表达式将会从源字符串的`RegExp.prototype.lastIndex`位置开始匹配，也就是进行“粘性匹配”。

```js
let str = "#foo#";
let regex = /foo/y;

regex.lastIndex = 1;
regex.test(str); // true
regex.lastIndex = 5;
regex.test(str); // false (lastIndex is taken into account with sticky flag)
regex.lastIndex; // 0 (reset after match failure)
```

### sticky 标志和 global 标志的不同点

如果正则表达式有粘性 `y` 标志，下一次匹配一定在 `lastIndex` 位置开始；如果正则表达式有全局 `g` 标志，下一次匹配可能在 `lastIndex` 位置开始，也可能在这个位置的后面开始。

```js
re = /\d/y;
while ((r = re.exec("123 456")))
  console.log(r, "AND re.lastIndex", re.lastIndex);

// [ '1', index: 0, input: '123 456', groups: undefined ] AND re.lastIndex 1
// [ '2', index: 1, input: '123 456', groups: undefined ] AND re.lastIndex 2
// [ '3', index: 2, input: '123 456', groups: undefined ] AND re.lastIndex 3
// ... and no more match.
```

如果使用带有全局标志`g`的正则表达式`re`，就会捕获字符串中的所有 6 个数字，而非 3 个

### 使用正则表达式和 Unicode 字符

正如上面表格提到的，`\w` 或 `\W` 只会匹配基本的 ASCII 字符；如 `a` 到 `z`、 `A` 到 `Z`、 `0` 到 `9` 及 `_`。

为了匹配其他语言中的字符，如西里尔（Cyrillic）或 希伯来语（Hebrew），要使用 `\uhhhh`，`hhhh` 表示以十六进制表示的字符的 Unicode 值。

下例展示了怎样从一个单词中分离出 Unicode 字符。

```js
let text = "Образец text на русском языке";
let regex = /[\u0400-\u04FF]+/g;

let match = regex.exec(text);
console.log(match[0]); // prints "Образец"
console.log(regex.lastIndex); // prints "7"

let match2 = regex.exec(text);
console.log(match2[0]); // prints "на" [did not print "text"]
console.log(regex.lastIndex); // prints "15"

// and so on
```

Unicode 属性转义特性引入了一种解决方案，它允许使用像\p{scx=Cyrl}这样简单的语句。这里有一个外部资源，用来获取 Unicode 中的不同区块范围：Regexp-unicode-block

### 从 URL 中提取子域名

```js
var url = "http://xxx.domain.com";
console.log(/[^.]+/.exec(url)[0].substr(7)); // logs "xxx"
```

**备注：** 使用浏览器内建的URL API而非正则表达式来解析 URL 是更好的做法

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-regexp-regular-expression-objects |

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

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

参见
--

* `core-js` 中很多现代 `RegExp` 特性（`dotAll`、`sticky` 标志、具名捕获组等）的 polyfill
* 正则表达式指南
* 正则表达式参考
* `String.prototype.match()`
* `String.prototype.replace()`
* `String.prototype.split()`


escape() - JavaScript

escape()
========

**已弃用:** 不再推荐使用该特性。虽然一些浏览器仍然支持它，但也许已从相关的 web 标准中移除，也许正准备移除或出于兼容性而保留。请尽量不要使用该特性，并更新现有的代码；参见本页面底部的兼容性表格以指导你作出决定。请注意，该特性随时可能无法正常工作。

概览
--

废弃的 **`escape()`** 方法生成新的由十六进制转义序列替换的字符串。使用 `encodeURI` 或 `encodeURIComponent` 代替。

语法
--
```

escape(str)
```

### 参数

`str`

待编码的字符串。

描述
--

`escape` 函数是全局对象的属性。特色字符如：`@*_+-./` 被排除在外。

字符的 16 进制格式值，当该值小于等于 0xFF 时，用一个 2 位转义序列：`%xx` 表示。大于的话则使用 4 位序列：%**u**xxxx 表示。

示例
--

```js
escape("abc123"); // "abc123"
escape("äöü"); // "%E4%F6%FC"
escape("ć"); // "%u0107"

// special characters
escape("@\*\_+-./"); // "@\*\_+-./"
```

规范
--

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

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

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

其他链接
----

* `encodeURI`
* `encodeURIComponent`


Math - JavaScript

Math
====

**`Math`** 是一个内置对象，它拥有一些数学常数属性和数学函数方法。`Math` 不是一个函数对象。

`Math` 用于 `Number` 类型。它不支持 `BigInt`。

描述
--

与其他全局对象不同的是，`Math` 不是一个构造器。`Math` 的所有属性与方法都是静态的。引用圆周率的写法是 `Math.PI`，调用正余弦函数的写法是 `Math.sin(x)`，`x` 是要传入的参数。`Math` 的常量是使用 JavaScript 中的全精度浮点数来定义的。

属性
--

`Math.E`

欧拉常数，也是自然对数的底数，约等于 `2.718`。

`Math.LN2`

`2` 的自然对数，约等于 `0.693`。

`Math.LN10`

`10` 的自然对数，约等于 `2.303`。

`Math.LOG2E`

以 `2` 为底的 `E` 的对数，约等于 `1.443`。

`Math.LOG10E`

以 `10` 为底的 `E` 的对数，约等于 `0.434`。

`Math.PI`

圆周率，一个圆的周长和直径之比，约等于 `3.14159`。

`Math.SQRT1_2`

二分之一 ½ 的平方根，同时也是 `2` 的平方根的倒数

1

2

，约等于 `0.707`。

`Math.SQRT2`

`2` 的平方根，约等于 `1.414`。

方法
--

**备注：** 需要注意的是，三角函数 `sin()`、`cos()`、`tan()`、`asin()`、`acos()`、`atan()` 和 `atan2()` 返回的值是*弧度*而非角度。若要转换，弧度除以 `(Math.PI / 180)` 即可转换为角度，同理，角度乘以这个数则能转换为弧度。

**备注：** 需要注意的是，很多 `Math` 函数都有一个精度，而且这个精度在不同实现中也是不相同的。这意味着不同的浏览器会给出不同的结果，甚至，在不同的系统或架构下，相同的 JS 引擎也会给出不同的结果！

`Math.abs(x)`

返回一个数的绝对值。

`Math.acos(x)`

返回一个数的反余弦值。

`Math.acosh(x)`

返回一个数的反双曲余弦值。

`Math.asin(x)`

返回一个数的反正弦值。

`Math.asinh(x)`

返回一个数的反双曲正弦值。

`Math.atan(x)`

返回一个数的反正切值。

`Math.atanh(x)`

返回一个数的反双曲正切值。

`Math.atan2(y, x)`

返回 `y/x` 的反正切值。

`Math.cbrt(x)`

返回一个数的立方根。

`Math.ceil(x)`

返回大于一个数的最小整数，即一个数向上取整后的值。

`Math.clz32(x)`

返回一个 32 位整数的前导零的数量。

`Math.cos(x)`

返回一个数的余弦值。

`Math.cosh(x)`

返回一个数的双曲余弦值。

`Math.exp(x)`

返回欧拉常数的参数次方，`E^x`，其中 `x` 为参数，`E` 是欧拉常数（2.718...，自然对数的底数）。

`Math.expm1(x)`

返回 `exp(x) - 1` 的值。

`Math.floor(x)`

返回小于一个数的最大整数，即一个数向下取整后的值。

`Math.fround(x)`

返回最接近一个数的单精度浮点型表示。

`Math.hypot([x[, y[, …]]])`

返回其所有参数平方和的平方根。

`Math.imul(x, y)`

返回 32 位整数乘法的结果。

`Math.log(x)`

返回一个数的自然对数（㏒e，即 ㏑）。

`Math.log1p(x)`

返回一个数加 1 的和的自然对数（㏒e，即 ㏑）。

`Math.log10(x)`

返回一个数以 10 为底数的对数。

`Math.log2(x)`

返回一个数以 2 为底数的对数。

`Math.max([x[, y[, …]]])`

返回零到多个数值中最大值。

`Math.min([x[, y[, …]]])`

返回零到多个数值中最小值。

`Math.pow(x, y)`

返回一个数的 y 次幂。

`Math.random()`

返回一个 0 到 1 之间的伪随机数。

`Math.round(x)`

返回四舍五入后的整数。

`Math.sign(x)`

返回一个数的符号，得知一个数是正数、负数还是 0。

`Math.sin(x)`

返回一个数的正弦值。

`Math.sinh(x)`

返回一个数的双曲正弦值。

`Math.sqrt(x)`

返回一个数的平方根。

`Math.tan(x)`

返回一个数的正切值。

`Math.tanh(x)`

返回一个数的双曲正切值。

`Math.toSource()`

返回字符串 `"Math"`。

`Math.trunc(x)`

返回一个数的整数部分，直接去除其小数点及之后的部分。

规范
--

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

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

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

参见
--

* `Number`


WeakMap - JavaScript

WeakMap
=======

**`WeakMap`** 是一种**键值对**的集合，其中的键必须是对象或非全局注册的符号，且值可以是任意的 JavaScript 类型，并且不会创建对它的键的强引用。换句话说，一个对象作为 `WeakMap` 的键存在，不会阻止该对象被垃圾回收。一旦一个对象作为键被回收，那么在 `WeakMap` 中相应的值便成为了进行垃圾回收的候选对象，只要它们没有其他的引用存在。唯一可以作为 `WeakMap` 的键的类型是非全局注册的符号，因为非全局注册的符号是保证唯一的，并且不能被重新创建。

`WeakMap` 允许将数据与对象相关联，而不阻止键对象被垃圾回收，即使值引用了键。然而，`WeakMap` 并不允许观察其键的生命周期，这就是为什么它不允许枚举；如果 `WeakMap` 提供了任何获得其键的列表的方法，那么这些列表将会依赖于垃圾回收的状态，这引入了不确定性。如果你想要可以获取键的列表，你应该使用 `Map` 而不是 `WeakMap`。

你可以在带键的集合指南的 WeakMap 对象部分了解更多关于 `WeakMap` 的内容。

描述
--

WeakMap 的键必须是可被垃圾回收的。大多数原始数据类型可以任意地被创建，且没有生命周期，因此不能作为键。对象和非全局注册的符号都可以作为键，因为它们是可被垃圾回收的。

### WeakMap 的意义

在 JavaScript 里，map API *可以*通过使其四个 API 方法共用两个数组（一个存放键，一个存放值）来实现。给这种映射设置值时会同时将键和值添加到这两个数组的末尾。从而使得键和值的索引在两个数组中相对应。当从该映射取值的时候，需要遍历所有的键，然后使用索引从存储值的数组中检索出相应的值。

但这样的实现会有两个很大的缺点：

1. 首先赋值和搜索操作都是 `O(n)` 的时间复杂度（*n* 是键值对的个数），因为这两个操作都需要遍历全部整个数组来进行匹配。
2. 另外一个缺点是可能会导致内存泄漏，因为数组会一直引用着每个键和值。这种引用使得垃圾回收算法不能回收处理他们，即使没有其他任何引用存在了。

相较之下，`WeakMap` 的键对象会强引用其值，直到该键对象被垃圾回收，但从那时起，它会变为弱引用。因此，`WeakMap`：

* 不会阻止垃圾回收，直到垃圾回收器移除了键对象的引用
* 任何值都可以被垃圾回收，只要它们的键对象没有被 `WeakMap` 以外的地方引用

当将键映射到与键相关的信息，而该信息*仅*在键未被垃圾回收的情况下具有价值时，`WeakMap` 是一个特别有用的构造。

但因为 `WeakMap` 不允许观察其键的生命周期，所以其键是不可枚举的。没有方法可以获得键的列表。如果有的话，该列表将会依赖于垃圾回收的状态，这引入了不确定性。如果你想要可以获得键的列表，你应该使用 `Map`。

构造函数
----

`WeakMap()`

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

实例属性
----

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

`WeakMap.prototype.constructor`

创建了该实例对象的构造函数。对于 `WeakMap` 实例，初始值是 `WeakMap` 构造函数。

`WeakMap.prototype[@@toStringTag]`

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

实例方法
----

`WeakMap.prototype.delete()`

删除任何与 `key` 关联的值。删除之后，`WeakMap.prototype.has(key)` 将会返回 `false`。

`WeakMap.prototype.get()`

返回与 `key` 关联的值，如果不存在则返回 `undefined`。

`WeakMap.prototype.has()`

返回一个布尔值，断言某个值是否已经与 `WeakMap` 对象中的 `key` 关联。

`WeakMap.prototype.set()`

给 `WeakMap` 对象中的 `key` 设置 `value`。返回该 `WeakMap` 对象。

示例
--

### 使用 WeakMap

```js
const wm1 = new WeakMap();
const wm2 = new WeakMap();
const wm3 = new WeakMap();
const o1 = {};
const o2 = function () {};
const o3 = window;

wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // value 可以是任意值，包括一个对象或一个函数
wm2.set(o2, undefined);
wm2.set(wm1, wm2); // 键和值可以是任意对象，甚至另外一个 WeakMap 对象

wm1.get(o2); // "azerty"
wm2.get(o2); // undefined，设置的值就是 undefined
wm2.get(o3); // undefined，wm2 中没有 o3 这个键

wm1.has(o2); // true
wm2.has(o2); // true（即使值是 undefined）
wm2.has(o3); // false

wm3.set(o1, 37);
wm3.get(o1); // 37

wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false
```

### 实现一个带有 .clear() 方法的类 WeakMap 的类

```js
class ClearableWeakMap {
  #wm;
  constructor(init) {
    this.#wm = new WeakMap(init);
  }
  clear() {
    this.#wm = new WeakMap();
  }
  delete(k) {
    return this.#wm.delete(k);
  }
  get(k) {
    return this.#wm.get(k);
  }
  has(k) {
    return this.#wm.has(k);
  }
  set(k, v) {
    this.#wm.set(k, v);
    return this;
  }
}
```

### 模拟私有成员

开发者可以使用 `WeakMap` 关联对象与私有数据，从而获得以下好处：

* 与 `Map` 相比，WeakMap 不持有键对象的强引用，因此元数据与对象本身共享同样的生命周期，避免内存泄漏。
* 与使用不可枚举对象和/或 `Symbol` 属性相比，WeakMap 位于对象外部，没有办法通过像 `Object.getOwnPropertySymbols`等的反射方法来检索元数据。
* 与闭包相比，构造函数可以复用同一个 WeakMap 对象来创建所有实例，从而节省内存，并且允许同一个类创建的不同实例读取彼此的私有成员。

```js
let Thing;

{
  const privateScope = new WeakMap();
  let counter = 0;

  Thing = function () {
    this.someProperty = "foo";

    privateScope.set(this, {
      hidden: ++counter,
    });
  };

  Thing.prototype.showPublic = function () {
    return this.someProperty;
  };

  Thing.prototype.showPrivate = function () {
    return privateScope.get(this).hidden;
  };
}

console.log(typeof privateScope);
// "undefined"

const thing = new Thing();

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1
```

这与下面使用了私有字段的示例类似：

```js
class Thing {
  static #counter = 0;
  #hidden;
  constructor() {
    this.someProperty = "foo";
    this.#hidden = ++Thing.#counter;
  }
  showPublic() {
    return this.someProperty;
  }
  showPrivate() {
    return this.#hidden;
  }
}

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1
```

### 关联元数据

`WeakMap` 可用于将元数据与对象关联，而不影响对象的生命周期。这与私有成员示例非常相似，因为私有成员也是以外部的形式模拟的元数据，不参与原型继承。

这个用例可以扩展到已经创建的对象上。例如，在网页上，我们可能希望将额外的数据与 DOM 元素相关联，而 DOM 元素可能在之后访问这些数据。一种常见的做法是将数据附加为属性：

```js
const buttons = document.querySelectorAll(".button");
buttons.forEach((button) => {
  button.clicked = false;
  button.addEventListener("click", () => {
    button.clicked = true;
    const currentButtons = [...document.querySelectorAll(".button")];
    if (currentButtons.every((button) => button.clicked)) {
      console.log("所有按钮被都被点击了！");
    }
  });
});
```

这种方法是有效的，但是有一些缺点：

* `clicked` 属性是可枚举的，因此它会出现在 `Object.keys(button)`、`for...in` 循环中，等等。可以通过使用 `Object.defineProperty()` 来缓解，但这会使代码更冗长。
* `clicked` 属性是一个普通的字符串属性，因此它可以被其他代码访问和覆盖。可以通过使用 `Symbol` 键来缓解，但键仍然可以通过 `Object.getOwnPropertySymbols()` 访问。

使用 `WeakMap` 来解决这些问题：

```js
const buttons = document.querySelectorAll(".button");
const clicked = new WeakMap();
buttons.forEach((button) => {
  clicked.set(button, false);
  button.addEventListener("click", () => {
    clicked.set(button, true);
    const currentButtons = [...document.querySelectorAll(".button")];
    if (currentButtons.every((button) => clicked.get(button))) {
      console.log("所有按钮被都被点击了！");
    }
  });
});
```

这段代码里，只有能访问 `clicked` 的代码才能知道每个按钮的点击状态，而外部代码就不能修改这些状态。此外，如果任何按钮从 DOM 中删除，那么相应的元数据将自动进行垃圾回收。

### 缓存

你可以将传递给函数的对象与函数的结果相关联，从而在再次传入相同的对象时，可以返回缓存的结果而无需再次执行函数。如果该函数是纯函数（即它不会改变任何外部对象或导致其他可观察到的副作用）的话，这非常有用。

```js
const cache = new WeakMap();
function handleObjectValues(obj) {
  if (cache.has(obj)) {
    return cache.get(obj);
  }
  const result = Object.values(obj).map(heavyComputation);
  cache.set(obj, result);
  return result;
}
```

只有当函数的输入是对象时才有效。此外，即使输入不再传入，结果依然永远保留在缓存中，更有效的方法是将 `Map` 与 `WeakRef` 对象配对使用，这允许你讲任何类型的输入值与各自的（很可能的）计算结果关联。有关更多详细信息，请参阅 WeakRef 和 FinalizationRegistry 示例。

规范
--

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

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

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

参见
--

* `core-js` 中 `WeakMap` 的 polyfill
* 带键的集合
* 使用 ECMAScript 6 WeakMap 隐藏实现细节，作者：尼克·菲茨杰拉德（2014）
* `Map`
* `Set`
* `WeakSet`


Date - JavaScript

Date
====

创建一个 JavaScript `Date` 实例，该实例呈现时间中的某个时刻。`Date` 对象则基于 Unix Time Stamp，即自 1970 年 1 月 1 日（UTC）起经过的毫秒数。

尝试一下
----

语法
--
```

new Date();
new Date(value);
new Date(dateString);
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
```

**备注：** 创建一个新`Date`对象的唯一方法是通过`new` 操作符，例如：`let now = new Date();`
 若将它作为常规函数调用（即不加 `new` 操作符），将返回一个字符串，而非 `Date` 对象。

### 参数

`Date()`构造函数有四种基本形式

#### 没有参数

如果没有提供参数，那么新创建的 Date 对象表示实例化时刻的日期和时间。

#### Unix 时间戳

`value`

一个 Unix 时间戳（Unix Time Stamp），它是一个整数值，表示自 1970 年 1 月 1 日 00:00:00 UTC（the Unix epoch）以来的毫秒数，忽略了闰秒。请注意大多数 Unix 时间戳功能仅精确到最接近的秒。

时间戳字符串 `dateString`

表示日期的字符串值。该字符串应该能被 `Date.parse()` 正确方法识别（即符合 IETF-compliant RFC 2822 timestamps 或 version of ISO8601）。

**备注：** 由于浏览器之间的差异与不一致性，强烈不推荐使用`Date`构造函数来解析日期字符串 (或使用与其等价的`Date.parse`)。对 RFC 2822 格式的日期仅有约定俗成的支持。对 ISO 8601 格式的支持中，仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间，与其他格式的串的处理不同。

#### 分别提供日期与时间的每一个成员

当至少提供了年份与月份时，这一形式的 `Date()` 返回的 `Date` 对象中的每一个成员都来自下列参数。没有提供的成员将使用最小可能值（对日期为`1`，其他为`0`）。

`year`

表示年份的整数值。0 到 99 会被映射至 1900 年至 1999 年，其他值代表实际年份。参见 示例。

`monthIndex`

表示月份的整数值，从 0（1 月）到 11（12 月）。

date可选

表示一个月中的第几天的整数值，从 1 开始。默认值为 1。

`hours` 可选

表示一天中的小时数的整数值 (24 小时制)。默认值为 0（午夜）。

`minutes` 可选

表示一个完整时间（如 01:10:00）中的分钟部分的整数值。默认值为 0。

`seconds` 可选

表示一个完整时间（如 01:10:00）中的秒部分的整数值。默认值为 0。

`milliseconds` 可选

表示一个完整时间的毫秒部分的整数值。默认值为 0。

使用注释
----

**备注：** 参数`monthIndex` 是从“0”开始计算的，这就意味着一月份为“0”，十二月份为“11”。

**备注：** 当 Date 作为构造函数调用并传入多个参数时，如果数值大于合理范围时（如月份为 13 或者分钟数为 70），相邻的数值会被调整。比如 new Date(2013, 13, 1) 等于 new Date(2014, 1, 1)，它们都表示日期 2014-02-01（注意月份是从 0 开始的）。其他数值也是类似，new Date(2013, 2, 1, 0, 70) 等于 new Date(2013, 2, 1, 1, 10)，都表示同一个时间：`2013-03-01T01:10:00`。

**备注：** 当 Date 作为构造函数调用并传入多个参数时，所定义参数代表的是当地时间。如果需要使用世界协调时 UTC，使用 `new Date(`Date.UTC(...)`)` 和相同参数。

简介
--

* 如果没有输入任何参数，则 Date 的构造器会依据系统设置的当前时间来创建一个 Date 对象。
* 如果提供了至少两个参数，其余的参数均会默认设置为 1（如果没有指定 day 参数）或者 0（如果没有指定 day 以外的参数）。
* JavaScript 的时间由世界标准时间（UTC）1970 年 1 月 1 日开始，用毫秒计时，一天由 86,400,000 毫秒组成。`Date` 对象的范围是 -100,000,000 天至 100,000,000 天（等效的毫秒值）。
* `Date` 对象为跨平台提供了统一的行为。时间属性可以在不同的系统中表示相同的时刻，而如果使用了本地时间对象，则反映当地的时间。
* `Date` 对象支持多个处理 UTC 时间的方法，也相应地提供了应对当地时间的方法。UTC，也就是我们所说的格林威治时间，指的是 time 中的世界时间标准。而当地时间则是指执行 JavaScript 的客户端电脑所设置的时间。
* 以一个函数的形式来调用 `Date` 对象（即不使用 `new` 操作符）会返回一个代表当前日期和时间的字符串。
属性
--

`Date.prototype` (en-US)

允许为 `Date` 对象添加属性。

`Date.length`

`Date.length` 的值是 7。这是该构造函数可接受的参数个数。

方法
--

`Date.now()`

返回自 1970-1-1 00:00:00 UTC（世界标准时间）至今所经过的毫秒数。

`Date.parse()`

解析一个表示日期的字符串，并返回从 1970-1-1 00:00:00 所经过的毫秒数。

**备注：** 由于浏览器差异和不一致，强烈建议不要使用`Date.parse`解析字符串。

`Date.UTC()`

接受和构造函数最长形式的参数相同的参数（从 2 到 7），并返回从 1970-01-01 00:00:00 UTC 开始所经过的毫秒数。

JavaScript `Date` 实例
--------------------

所有的 `Date` 实例都继承自 `Date.prototype` (en-US)。修改 `Date` 构造函数的原型对象会影响到所有的 `Date` 实例。

### 实例属性

`Date.prototype.constructor`

返回创建了实例的构造函数，默认是 `Date` 构造函数。

### 实例方法

`Date.prototype.getDate()`

根据本地时间，返回一个指定的 `Date` 对象为一个月中的哪一日（`1`-`31`）。

`Date.prototype.getDay()`

根据本地时间，返回一个指定的 `Date` 对象是在一周中的第几天（`0`-`6`），0 表示星期天。

`Date.prototype.getFullYear()`

根据本地时间，返回一个指定的 `Date` 对象的完整年份（四位数年份）。

`Date.prototype.getHours()`

根据本地时间，返回一个指定的 `Date` 对象的小时（`0`–`23`）。

`Date.prototype.getMilliseconds()`

根据本地时间，返回一个指定的 `Date` 对象的毫秒数（`0`–`999`）。

`Date.prototype.getMinutes()`

根据本地时间，返回一个指定的 `Date` 对象的分钟数（`0`–`59`）。

`Date.prototype.getMonth()`

根据本地时间，返回一个指定的 `Date` 对象的月份（`0`–`11`），0 表示一年中的第一月。

`Date.prototype.getSeconds()`

根据本地时间，返回一个指定的 `Date` 对象的秒数（`0`–`59`）。

`Date.prototype.getTime()`

返回一个数值，表示从 1970 年 1 月 1 日 0 时 0 分 0 秒（UTC，即协调世界时）距离该 `Date` 对象所代表时间的毫秒数。（更早的时间会用负数表示）

`Date.prototype.getTimezoneOffset()`

返回协调世界时（UTC）相对于当前时区的时间差值，单位为分钟。

`Date.prototype.getUTCDate()`

以协调世界时为标准，返回一个指定的 `Date` 对象为一个月中的哪一日（`1`-`31`）。

`Date.prototype.getUTCDay()`

以协调世界时为标准，返回一个指定的 `Date` 对象是在一周中的第几天（`0`-`6`），0 表示星期天。

`Date.prototype.getUTCFullYear()`

以协调世界时为标准，返回一个指定的 `Date` 对象的完整年份（四位数年份）。

`Date.prototype.getUTCHours()`

以协调世界时为标准，返回一个指定的 `Date` 对象的小时（`0`–`23`）。

`Date.prototype.getUTCMilliseconds()`

以协调世界时为标准，返回一个指定的 `Date` 对象的毫秒数（`0`–`999`）。

`Date.prototype.getUTCMinutes()`

以协调世界时为标准，返回一个指定的 `Date` 对象的分钟数（`0`–`59`）。

`Date.prototype.getUTCMonth()`

以协调世界时为标准，返回一个指定的 `Date` 对象的月份（`0`–`11`），0 表示一年中的第一月。

`Date.prototype.getUTCSeconds()`

以协调世界时为标准，返回一个指定的 `Date` 对象的秒数（`0`–`59`）。

`Date.prototype.getYear()`

根据本地时间，返回一个指定的 `Date` 对象的相对年份（相对 1900 年，通常是 2 到 3 位数字）。请改用 `getFullYear` 。

`Date.prototype.setDate()`

根据本地时间，设置一个 `Date` 对象在所属月份中的天数。

`Date.prototype.setFullYear()`

根据本地时间，设置一个 `Date` 对象的完整年份（四位数年份）。

`Date.prototype.setHours()`

根据本地时间，设置一个 `Date` 对象的小时数。

`Date.prototype.setMilliseconds()`

根据本地时间，设置一个 `Date` 对象的豪秒数。

`Date.prototype.setMinutes()`

根据本地时间，设置一个 `Date` 对象的分钟数。

`Date.prototype.setMonth()`

根据本地时间，设置一个 `Date` 对象的月份。

`Date.prototype.setSeconds()`

根据本地时间，设置一个 `Date` 对象的秒数。

`Date.prototype.setTime()`

用一个从 1970-1-1 00:00:00 UTC 计时的毫秒数来为一个 `Date` 对象设置时间。用负数来设置更早的时间。

`Date.prototype.setUTCDate()`

以协调世界时为标准，设置一个 `Date` 对象在所属月份中的天数。

`Date.prototype.setUTCFullYear()`

以协调世界时为标准，设置一个 `Date` 对象的完整年份（四位数年份）。

`Date.prototype.setUTCHours()`

以协调世界时为标准，设置一个 `Date` 对象的小时数。

`Date.prototype.setUTCMilliseconds()`

以协调世界时为标准，设置一个 `Date` 对象的豪秒数。

`Date.prototype.setUTCMinutes()`

以协调世界时为标准，设置一个 `Date` 对象的分钟数。

`Date.prototype.setUTCMonth()`

以协调世界时为标准，设置一个 `Date` 对象的月份。

`Date.prototype.setUTCSeconds()`

以协调世界时为标准，设置一个 `Date` 对象的秒数。

`Date.prototype.setYear()`

根据本地时间，设置一个 `Date` 对象的相对年份（相对 1900 年，通常是 2 到 3 位数字）。请改用 `setFullYear` 。

`Date.prototype.toDateString()`

以美式英语和人类易读的表述形式返回一个 `Date` 对象日期部分的字符串。

`Date.prototype.toISOString()`

将指定 `Date` 对象转换成 ISO 格式表述的字符串并返回。

`Date.prototype.toJSON()`

返回指定 `Date` 对象调用 `toISOString()` 方法的返回值。在 `JSON.stringify()` 中使用。

`Date.prototype.toLocaleDateString()`

返回一个表述指定 `Date` 对象的日期部分字符串。该字符串格式因不同语言而不同。

`Date.prototype.toLocaleString()`

返回一个表述指定 `Date` 对象的字符串。该字符串格式因不同语言而不同。

`Date.prototype.toLocaleTimeString()`

返回一个表述指定 `Date` 对象时间部分的的字符串。该字符串格式因不同语言而不同。

`Date.prototype.toString()`

返回一个字符串，表示该 `Date` 对象。覆盖了 `Object.prototype.toString()` 方法。

`Date.prototype.toTimeString()`

以人类易读形式返回一个 `Date` 对象时间部分的字符串，该字符串以美式英语格式化。

`Date.prototype.toUTCString()`

使用 UTC 时区，把一个 `Date` 对象转换为一个字符串。

`Date.prototype.valueOf()`

返回一个 `Date` 对象的原始值。覆盖了 `Object.prototype.valueOf()` 方法。

示例
--

### 创建一个日期对象的几种方法

下例展示了用来创建一个日期对象的多种方法。

**备注：** 由于浏览器差异和不一致性，强烈建议不要使用`Date`构造函数（和`Date.parse`，它们是等效的）解析日期字符串。

```js
var today = new Date();
var birthday = new Date("December 17, 1995 03:24:00");
var birthday = new Date("1995-12-17T03:24:00");
var birthday = new Date(1995, 11, 17);
var birthday = new Date(1995, 11, 17, 3, 24, 0);
```

### 将两位数年份映射为 1900 - 1999 年

为了创建和获取 0 到 99 之间的年份，应使用 `Date.prototype.setFullYear()` 和 `Date.prototype.getFullYear()` 方法。

```js
var date = new Date(98, 1); // Sun Feb 01 1998 00:00:00 GMT+0000 (GMT)

// 已弃用的方法，同样将 98 映射为 1998
date.setYear(98); // Sun Feb 01 1998 00:00:00 GMT+0000 (GMT)

date.setFullYear(98); // Sat Feb 01 0098 00:00:00 GMT+0000 (BST)
```

### 计算经过的时间

下例展示了如何以毫秒精度计算两个日期对象的时间差：

由于不同日期、月份、年份长度的不同（日期长度不同来自夏令时的切换），使用大于秒、分钟、小时的单位表示经过的时间会遇到很多问题，在使用前需要经过详尽的调研。

```js
// 使用 Date 对象
var start = Date.now();

// 调用一个消耗一定时间的方法：
doSomethingForALongTime();
var end = Date.now();
var elapsed = end - start; // 以毫秒计的运行时长
```

```js
// 使用内建的创建方法
var start = new Date();

// 调用一个消耗一定时间的方法：
doSomethingForALongTime();
var end = new Date();
var elapsed = end.getTime() - start.getTime(); // 运行时间的毫秒值
```

```js
// to test a function and get back its return
function printElapsedTime(fTest) {
  var nStartTime = Date.now(),
    vReturn = fTest(),
    nEndTime = Date.now();
  alert("Elapsed time: " + String(nEndTime - nStartTime) + " milliseconds");
  return vReturn;
}
yourFunctionReturn = printElapsedTime(yourFunction);
```

**备注：** 在支持 `Web Performance API` 的高精细度（high-resolution）时间功能的浏览器中，`Performance.now()` 提供的所经过的时间比 `Date.now()` 更加可靠、精确。

### 获取自 Unix 起始时间以来经过的秒数

```js
var seconds = Math.floor(Date.now() / 1000);
```

注意此处需要返回一个整数（仅做除法得到的不是整数），并且需要返回实际已经经过的秒数（所以这里使用了`Math.floor()`而不是`Math.round()`).

规范
--

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

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

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


Generator - JavaScript

Generator
=========

**`Generator`** 对象由生成器函数返回并且它符合可迭代协议和迭代器协议。

`Generator` 是隐藏类 `Iterator` 的子类。

尝试一下
----

构造函数
----

`Generator` 构造函数并不是全局可用的。`Generator` 的实例必须从生成器函数返回：

```js
function\* generator() {
  yield 1;
  yield 2;
  yield 3;
}

const gen = generator(); // "Generator { }"

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

实际上，并没有对应 `Generator` 构造函数的 JavaScript 实体。只有一个隐藏对象，其是所有由生成器函数创建的对象所共享的原型对象。这个对象通常被风格化为 `Generator.prototype` 来使其看起来像是一个类，但它更恰当的称呼应该是 `GeneratorFunction.prototype.prototype`，因为 `GeneratorFunction` 是一个实际的 JavaScript 实体。

实例属性
----

这些属性定义于 `Generator.prototype` 并由所有 `Generator` 实例所共享。

`Generator.prototype.constructor`

创建实例对象的构造函数。对于 `Generator` 实例，其初始值是 `GeneratorFunction.prototype`。

**备注：** `Generator` 对象不会存储创建它们的生成器函数的引用。

`Generator.prototype[@@toStringTag]`

`@@toStringTag` 属性的初始值是字符串 `"Generator"`。该属性被 `Object.prototype.toString()` 使用。

实例方法
----

*同时也从其父类 `Iterator` 继承实例方法*。

`Generator.prototype.next()`

返回 `yield` 表达式生成的值。

`Generator.prototype.return()`

类似于在当前的生成器主体的暂停位置插入 `return` 语句，该语句结束了生成器并且允许生成器与 `try...finally` 块相组合时，执行任何清理任务。

`Generator.prototype.throw()`

类似于在当前的生成器主体的暂停位置插入 `throw` 语句，该语句通知生成器有错误的情况并且允许其处理错误或执行清理并自行关闭。

示例
--

### 无穷迭代器

通过生成器函数，值只有在其被需要时才会进行计算。因此，生成器允许我们定义一个潜在的无穷数据结构。

```js
function\* infinite() {
  let index = 0;

  while (true) {
    yield index++;
  }
}

const generator = infinite(); // "Generator { }"

console.log(generator.next().value); // 0
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
// …
```

规范
--

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

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

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

参见
--

* `function*`
* `function*` 表达式
* `GeneratorFunction`
* 迭代器协议


Intl - JavaScript

Intl
====

**`Intl`** 对象是 ECMAScript 国际化 API 的一个命名空间，它提供了精确的字符串对比、数字格式化，和日期时间格式化。`Collator`，`NumberFormat` 和 `DateTimeFormat` 对象的构造函数是 `Intl` 对象的属性。本页文档内容包括了这些属性，以及国际化使用的构造器和其他语言的方法等常见的功能。

属性
--

`Intl.Collator`

collators 的构造函数，用于启用对语言敏感的字符串比较的对象。

`Intl.DateTimeFormat`

用于启用语言敏感的日期和时间格式的对象的构造函数。

`Intl.ListFormat`

Constructor for objects that enable language-sensitive list formatting.

`Intl.NumberFormat`

用于启用语言敏感数字格式的对象的构造函数。

`Intl.PluralRules`

用于启用多种敏感格式和多种语言语言规则的对象的构造函数。

`Intl.RelativeTimeFormat`

Constructor for objects that enable language-sensitive relative time formatting.

方法
--

`Intl.getCanonicalLocales()`

返回规范区域名称（canonical locale name）。

语言区域识别和判定
---------

国际化的构造函数和其他构造函数的几个语言敏感的方法（可参考下方的参见）一样，使用同样的模式来识别语言区域和确定使用哪一种语言格式：他们都接收 `locales` 和 `options` 参数，使用 `options.localeMatcher` 属性指定的一个算法来对比应用请求的和支持的语言区域，来确定使用哪一个语言区域。

### `locales` 参数

`locales` 参数必须是一个 BCP 47 语言标记的字符串，或者是一个包括多个语言标记的数组。如果 `locales` 参数未提供或者是 undefined，便会使用运行时默认的 locale。

一个 BCP 47 语言标记代表了一种语言或者区域（两者没有很大的区别）。在其最常见的格式中，它以这样的顺序囊括了这些内容：语言代码，脚本代码，和国家代码，全部由连字符分隔开。例如：

* `"hi"`：印地语 (primary language)。
* `"de-AT"`: 在奥地利使用的德语 (primary language with country code)。
* `"zh-Hans-CN"`：在中国使用的简体中文 (primary language with script and country codes)。

在 BCP 47 中表示语言，脚本，国家（区域）和变体（少用）的语言子标记含义可以在IANA 语言子标记注册 中找到。

BCP 47 也支持扩展，其中一个和 JavaScript 国际化方法相关的是："u"（Unicode）扩展。它可以用于请求一个自定义区域特定行为的 `Collator`，`NumberFormat`，或者 `DateTimeFormat` 对象。例如：

* `"de-DE-u-co-phonebk"`：使用德语的电话簿排序变体，这会把元音变音扩展成字符对：ä → ae, ö → oe, ü → ue。
* `"th-TH-u-nu-thai"`：在数字格式中使用泰语的数值表示（๐, ๑, ๒, ๓, ๔, ๕, ๖, ๗, ๘, ๙）
* `"ja-JP-u-ca-japanese"`：在日期和时间格式化中使用日本的日历表示方式，所以 2013 会表示为平成 25。
* `"en-GB-u-ca-islamic"`: use British English with the Islamic (Hijri) calendar, where the Gregorian date 14 October, 2017 is the Hijri date 24 Muharram, 1439.
### 语言区域判定

`locales` 参数，在除去所有的 Unicode 扩展之后，会被转化成来自应用的优先请求。运行时拿它和可用的语言区域做对比然后选择出最合适的一个。有两种匹配算法：“查找”匹配遵循 BCP 47 中指定的查找算法；“最佳命中”匹配器会让运行时至少提供一个语言区域，但合适请求的结果可能会比查找算法的要多。如果应用没有提供一个 locales 参数，或者运行时没有一个匹配请求的语言区域，那么会使用运行时默认的语言区域。匹配器可以使用 `options` 参数的一个属性来进行选择（见下方）。

如果选中的语言标记有一个 Unicode 扩展子字符串，这个扩展会用于自定义构造对象或者方法的行为。每一个构造函数或者方法仅支持 Unicode 扩展定义的 key 的一个子集，和依赖于语言标记的支持的值。例如，`“co”`这个 key（collation）只在 `Collator` 中支持，它的值“phonebk”只在德语中支持。

### `options` 参数

`options` 参数必须是一个对象，其属性值在不同的构造函数和方法中会有所变化。如果 `options` 参数未提供或者为 undefined，所有的属性值则使用默认的。

所有语言敏感的构造函数和方法都支持的一个属性是：`localeMatcher` 属性，它的值必须是字符串“lookup”或者“best fit”，用于选择上边描述的语言区域匹配算法。

规范
--

| Specification |
| --- |
| ECMAScript Internationalization API Specification # intl-object |

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

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

参见
--

* 介绍：The ECMAScript Internationalization API
* 构造函数
    + `Intl.Collator`
    + `Intl.DateTimeFormat`
    + `Intl.ListFormat`
    + `Intl.NumberFormat`
    + `Intl.PluralRules`
    + `Intl.RelativeTimeFormat`
* 方法
    + `String.prototype.localeCompare()`
    + `Number.prototype.toLocaleString()`
    + `Date.prototype.toLocaleString()`
    + `Date.prototype.toLocaleDateString()`
    + `Date.prototype.toLocaleTimeString()`


Uint8ClampedArray - JavaScript

Uint8ClampedArray
=================

**`Uint8ClampedArray`（8 位无符号整型固定数组）** 类型化数组表示一个由值固定在 0-255 区间的 8 位无符号整型组成的数组；如果你指定一个在 [0,255] 区间外的值，它将被替换为 0 或 255；如果你指定一个非整数，那么它将被设置为最接近它的整数。（数组）内容被初始化为 0。一旦（数组）被创建，你可以使用对象的方法引用数组里的元素，或使用标准的数组索引语法（即使用方括号标记）。

语法
--
```

new Uint8ClampedArray(length);
new Uint8ClampedArray(typedArray);
new Uint8ClampedArray(object);
new Uint8ClampedArray(buffer [, byteOffset [, length]]);
```

关于构造函数语法和参数的更多信息，参见 *TypedArray*。

属性
--

`Uint8ClampedArray.BYTES_PER_ELEMENT`

返回元素大小的一个数值。对 `Uint8ClampedArray` 而言是 1。

`Uint8ClampedArray.prototype.length`

静态长度属性值为 0。对于实际长度（元素的数量），见 `Uint8ClampedArray.prototype.length`。

`Uint8ClampedArray.prototype` (en-US)

原型是 *TypedArray*（类型化数组）对象。

方法
--

`Uint8ClampedArray.from()`

从一个类数组或可枚举对象创建一个新的 `Uint8ClampedArray`。参见 `Array.from()`。

`Uint8ClampedArray.of()`

通过一个可选数量参数来创建一个新的 `Uint8ClampedArray`。参见 `Array.of()`。

Uint8ClampedArray 原型
--------------------

所有的 `Uint8ClampedArray` 对象继承自 `%TypedArray%.prototype` (en-US)。

### 属性

`Uint8ClampedArray.prototype.constructor`

返回创建一个实例原型的函数。这是 `Uint8ClampedArray` 默认的构造函数。

`Uint8ClampedArray.prototype.buffer` 只读

返回由 `Uint8ClampedArray` 引用的 `ArrayBuffer` 。在创建时所固定下来，因此**只能读取**。

`Uint8ClampedArray.prototype.byteLength` 只读

返回从 `ArrayBuffer` 开始的 `Uint8ClampedArray` 的（字节的）长度。在创建时所固定下来，因此**只能读取**。

`Uint8ClampedArray.prototype.byteOffset` 只读

返回从 `ArrayBuffer` 开始的 `Uint8ClampedArray` 的（字节的）偏移。在创建时所固定下来，因此**只能读取**。

`Uint8ClampedArray.prototype.length` 只读

返回 `UintClamped8Array` 具有的元素数量。在创建时所固定下来，因此**只能读取**。

### 方法

`Uint8ClampedArray.prototype.copyWithin()`

复制数组内一段数组元素的序列。参见 `Array.prototype.copyWithin()`。

`Uint8ClampedArray.prototype.entries()`

返回一个新的包含数组中每个索引对应的键/值对的数组迭代器对象。参见 `Array.prototype.entries()`。

`Uint8ClampedArray.prototype.every()`

测试数组里的所有元素是否通过所提供的函数的测试。参见 `Array.prototype.every()`。

`Uint8ClampedArray.prototype.fill()`

用一个固定值填充一个数组内的从起始索引到结束索引的全部元素。参见 `Array.prototype.fill()`。

`Uint8ClampedArray.prototype.filter()`

由该数组中所有经所提供的筛选函数返回为 true 的元素创建一个新数组。参见 `Array.prototype.filter()`。

`Uint8ClampedArray.prototype.find()`

如果数组里的一个元素符合所提供的测试函数则返回找到的这个值，如果没有找到则返回 `undefined`。参见 `Array.prototype.find()`。

`Uint8ClampedArray.prototype.findIndex()`

如果数组里的一个元素符合所提供的测试函数则返回找到的索引，如果没有找到则返回 -1。参见 `Array.prototype.findIndex()`。

`Uint8ClampedArray.prototype.forEach()`

对数组内的每个元素调用一个函数。参见 `Array.prototype.forEach()`。

`Uint8ClampedArray.prototype.includes()`
实验性

确定一个类型化数组是否包含一个特定的元素，对应地返回 `true` 或 `false`。参见 `Array.prototype.includes()`。

`Uint8ClampedArray.prototype.indexOf()`

Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found. See also `Array.prototype.indexOf()`.

`Uint8ClampedArray.prototype.join()`

Joins all elements of an array into a string. See also `Array.prototype.join()`.

`Uint8ClampedArray.prototype.keys()`

Returns a new `Array Iterator` that contains the keys for each index in the array. See also `Array.prototype.keys()`.

`Uint8ClampedArray.prototype.lastIndexOf()`

Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found. See also `Array.prototype.lastIndexOf()`.

`Uint8ClampedArray.prototype.map()`

Creates a new array with the results of calling a provided function on every element in this array. See also `Array.prototype.map()`.

`Uint8ClampedArray.prototype.move()`
非标准
 未实现

Former non-standard version of `Uint8ClampedArray.prototype.copyWithin()`.

`Uint8ClampedArray.prototype.reduce()`

Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value. See also `Array.prototype.reduce()`.

`Uint8ClampedArray.prototype.reduceRight()`

Apply a function against an accumulator and each value of the array (from right-to-left) as to reduce it to a single value. See also `Array.prototype.reduceRight()`.

`Uint8ClampedArray.prototype.reverse()`

Reverses the order of the elements of an array — the first becomes the last, and the last becomes the first. See also `Array.prototype.reverse()`.

`Uint8ClampedArray.prototype.set()`

Stores multiple values in the typed array, reading input values from a specified array.

`Uint8ClampedArray.prototype.slice()`

Extracts a section of an array and returns a new array. See also `Array.prototype.slice()`.

`Uint8ClampedArray.prototype.some()`

Returns true if at least one element in this array satisfies the provided testing function. See also `Array.prototype.some()`.

`Uint8ClampedArray.prototype.sort()`

Sorts the elements of an array in place and returns the array. See also `Array.prototype.sort()`.

`Uint8ClampedArray.prototype.subarray()`

Returns a new `Uint8ClampedArray` from the given start and end element index.

`Uint8ClampedArray.prototype.values()`

Returns a new `Array Iterator` object that contains the values for each index in the array. See also `Array.prototype.values()`.

`Uint8ClampedArray.prototype.toLocaleString()`

Returns a localized string representing the array and its elements. See also `Array.prototype.toLocaleString()`.

`Uint8ClampedArray.prototype.toString()`

Returns a string representing the array and its elements. See also `Array.prototype.toString()`.

`Uint8ClampedArray.prototype[@@iterator]()`

Returns a new `Array Iterator` object that contains the values for each index in the array.

示例
--

创建一个 `Uint8ClampedArray` 的不同方式：

```js
// From a length
var uintc8 = new Uint8ClampedArray(2);
uintc8[0] = 42;
uintc8[1] = 1337;
console.log(uintc8[0]); // 42
console.log(uintc8[1]); // 255 (clamped)
console.log(uintc8.length); // 2
console.log(uintc8.BYTES\_PER\_ELEMENT); // 1

// From an array
var arr = new Uint8ClampedArray([21, 31]);
console.log(arr[1]); // 31

// From another TypedArray
var x = new Uint8ClampedArray([21, 31]);
var y = new Uint8ClampedArray(x);
console.log(y[0]); // 21

// From an ArrayBuffer
var buffer = new ArrayBuffer(8);
var z = new Uint8ClampedArray(buffer, 1, 4);

// From an iterable
var iterable = (function\* () {
  yield\* [1, 2, 3];
})();
var uintc8 = new Uint8ClampedArray(iterable);
// Uint8ClampedArray[1, 2, 3]
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # table-49 |

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

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

兼容性注意事项
-------

从 ECMAScript 2015 开始， `Uint8ClampedArray` 构造函数需要用一个 `new` 操作符来构建。从现在开始，不使用 `new` 来调用一个 `Uint8ClampedArray` 构造函数将会抛出一个 `TypeError`。

```js
var dv = Uint8ClampedArray([1, 2, 3]);
// TypeError: calling a builtin Uint8ClampedArray constructor
// without new is forbidden
```

```js
var dv = new Uint8ClampedArray([1, 2, 3]);
```

参见
--

* JavaScript typed arrays
* `ArrayBuffer`
* `DataView`


URIError - JavaScript

URIError
========

**`URIError`** 对象用来表示以一种错误的方式使用全局 URI 处理函数而产生的错误。

`URIError` 是 可序列化对象，所以可以使用 `structuredClone()` 克隆它，或者在 Worker 间使用 `postMessage()` 拷贝这个对象。

构造函数
----

`URIError()` (en-US)

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

实例属性
----

`URIError.prototype.message`

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

`URIError.prototype.name`

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

`URIError.prototype.cause`

导致错误的原因。继承自 `Error`。

`URIError.prototype.fileName`
非标准

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

`URIError.prototype.lineNumber`
非标准

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

`URIError.prototype.columnNumber`
非标准

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

`URIError.prototype.stack`
非标准

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

示例
--

### 捕获一个 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`
* `decodeURI()`
* `decodeURIComponent()`
* `encodeURI()`
* `encodeURIComponent()`


Uint8Array - JavaScript

Uint8Array
==========

**`Uint8Array`** 数组类型表示一个 8 位无符号整型数组，创建时内容被初始化为 0。创建完后，可以以对象的方式或使用数组下标索引的方式引用数组中的元素。

语法格式
----
```

new Uint8Array(); // ES2017 最新语法
new Uint8Array(length); // 创建初始化为 0 的，包含 length 个元素的无符号整型数组
new Uint8Array(typedArray);
new Uint8Array(object);
new Uint8Array(buffer [, byteOffset [, length]]);
```

构造语法和参数的更多信息请参见 *TypedArray*.

属性
--

`Uint8Array.BYTES_PER_ELEMENT`

返回数组中元素的字节数，Uint8Array 中返回 1 字节。

Uint8Array.length

静态属性 length 一直为 0。想获知其真实长度（元素个数），请参阅 `Uint8Array.prototype.length`。

`Uint8Array.prototype` (en-US)

*TypedArray* 对象的原型。

方法
--

`Uint8Array.from()`

从一个数组或可迭代的对象创建一个新的`Uint8Array`数组，可参见`Array.from()`.

`Uint8Array.of()`

通过一个可变数目的参数创建一个新的`Uint8Array`数组，可参见`Array.of()`.

`Uint8Array` 原型声明
-----------------

所有的`Uint8Array 对象继承自` `%TypedArray%.prototype` (en-US).

### 属性

`Uint8Array.prototype.constructor`

返回创建实例属性的函数，默认为 `Uint8Array` 构造器。

`Uint8Array.prototype.buffer` 只读

返回由 `Uint8Array`引用的 `ArrayBuffer` ，在构造时期固定，所以是**只读**的。

`Uint8Array.prototype.byteLength` 只读

返回`Uint8Array`长度（字节数）。在构造时期固定，所以是 **只读的**。

`Uint8Array.prototype.byteOffset` 只读

返回`Uint8Array` 距离其 `ArrayBuffer` 起始位置的偏移（字节数）。在构造时期固定，所以是 **只读的**。

`Uint8Array.prototype.length` 只读

返回保存在 `Uint8Array`中的元素数量。在构造时期固定，所以是 **只读的**。

### 方法

`Uint8Array.prototype.copyWithin()`

复制数组中的元素序列，请参见 `Array.prototype.copyWithin()`。

`Uint8Array.prototype.entries()`

返回新的`Array Iterator` 对象，含有数组中每个下标处的键值对。请参见`Array.prototype.entries()`.

`Uint8Array.prototype.every()`

测试数组中所有元素是否都能通过由函数提供的测试。请参见 `Array.prototype.every()`。

`Uint8Array.prototype.fill()`

使用静态值填充从起始下标到终止下标的数组元素。请参见 `Array.prototype.fill()`。

`Uint8Array.prototype.filter()`

创建新的数组，含有数组中给定过滤器返回 true 的所有元素。请参见`Array.prototype.filter()`.

`Uint8Array.prototype.find()`

如果数组中的元素满足提供的测试函数，返回找到的值，如果没有找到则返回 `undefined`。请参见 `Array.prototype.find()`。

`Uint8Array.prototype.findIndex()`

如果数组中的元素满足提供的测试函数，返回找到的下标，如果没有找到则返回 -1。请参见 `Array.prototype.findIndex()`.

`Uint8Array.prototype.forEach()`

对数组的每个元素调用字符串 `Array.prototype.forEach()`。

`Uint8Array.prototype.includes()`
实验性

判断类型化数组是否包含特定值，如果包含返回 `true`，否则返回`false`。另见`Array.prototype.includes()`。

`Uint8Array.prototype.indexOf()`

返回数组中等于特定值的第一个元素（下标最小），如果没有找到则返回 -1，请参见 `Array.prototype.indexOf()`.

`Uint8Array.prototype.join()`

将数组中所有元素连接为字符串。请参见 `Array.prototype.join()`。

`Uint8Array.prototype.keys()`

返回新的`Array Iterator` ，含有数组中每个下标的键，请参见 `Array.prototype.keys()`。

`Uint8Array.prototype.lastIndexOf()`

返回数组中等于特定值的最后一个元素（下标最大），如果没有找到则返回 -1，请参见 `Array.prototype.lastIndexOf()`。

`Uint8Array.prototype.map()`

使用在该数组的每个元素上调用函数的结果创建新数组，请参见`Array.prototype.map()`。

`Uint8Array.prototype.move()`
非标准
 未实现

`Uint8Array.prototype.copyWithin()`的之前的非标准版本。

`Uint8Array.prototype.reduce()`

对累加器和数组的每个值应用函数（从左到右），使其归约为单一的值，另见 `Array.prototype.reduce()`。

`Uint8Array.prototype.reduceRight()`

对累加器和数组的每个值应用函数（从右到左），使其归约为单一的值，另见 `Array.prototype.reduceRight()`。

`Uint8Array.prototype.reverse()`

翻转数组中的元素顺序 — 第一个变为最后，最后变为第一个。另见 `Array.prototype.reverse()`。

`Uint8Array.prototype.set()`

在类型化数组中储存多个值，从特定数组中读取输入。

`Uint8Array.prototype.slice()`

提取数组的某个部分并返回新的数组，请参见 `Array.prototype.slice()`。

`Uint8Array.prototype.some()`

如果数组中至少一个元素满足给定的测试函数，则返回`true`。请参见`Array.prototype.some()`。

`Uint8Array.prototype.sort()`

原地排序数组中的元素，并返回该数组，请参见 `Array.prototype.sort()`。

`Uint8Array.prototype.subarray()`

`从给定的元素起始和终止下标返回新的 Uint8Array` 。

`Uint8Array.prototype.values()`

返回新的 `Array Iterator` 对象，含有数组每个下标处的值，请参见 `Array.prototype.values()`。

`Uint8Array.prototype.toLocaleString()`

返回表示数组及其元素的本地化字符串，请参见 `Array.prototype.toLocaleString()`。

`Uint8Array.prototype.toString()`

返回表示数组及其元素的字符串。请参见 `Array.prototype.toString()`。

`Uint8Array.prototype[@@iterator]()`

`返回新的 Array Iterator` 对象，包含数组中每个下标处的值。

示例
--

```js
// 来自长度
var uint8 = new Uint8Array(2);
uint8[0] = 42;
console.log(uint8[0]); // 42
console.log(uint8.length); // 2
console.log(uint8.BYTES\_PER\_ELEMENT); // 1

// 来自数组
var arr = new Uint8Array([21, 31]);
console.log(arr[1]); // 31

// 来自另一个 TypedArray
var x = new Uint8Array([21, 31]);
var y = new Uint8Array(x);
console.log(y[0]); // 21

// 来自 ArrayBuffer
var buffer = new ArrayBuffer(8);
var z = new Uint8Array(buffer, 1, 4);

// 来自一个迭代器
var iterable = (function\* () {
  yield\* [1, 2, 3];
})();
var uint8 = new Uint8Array(iterable);
// Uint8Array[1, 2, 3]
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # table-49 |

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

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

兼容性说明
-----

从 ECMAScript 2015 开始，`Uint8Array` 构造函数需要通过 `new` 操作符调用。即日起如果没有使用 `new` 调用 `Uint8Array` 的构造函数，将会抛出 `TypeError` 。

```js
var dv = Uint8Array([1, 2, 3]);
// TypeError: calling a builtin Uint8Array constructor
// 不使用 new 将会被禁止
```

```js
var dv = new Uint8Array([1, 2, 3]);
```

相关内容
----

* JavaScript 类型化数组
* `ArrayBuffer`
* `DataView`


GeneratorFunction - JavaScript

GeneratorFunction
=================

**`GeneratorFunction`** 对象为生成器函数提供了方法。在 JavaScript 中，每个生成器函数实际上都是一个 `GeneratorFunction` 对象。

请注意，`GeneratorFunction` *不是*全局对象。可以通过以下代码来获取它：

```js
const GeneratorFunction = function\* () {}.constructor;
```

`GeneratorFunction` 是 `Function` 的子类。

尝试一下
----

构造函数
----

`GeneratorFunction()`

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

实例属性
----

*也从其父类 `Function` 继承实例属性*。

这些属性定义于 `GeneratorFunction.prototype` 并由所有 `GeneratorFunction` 实例所共享。

`GeneratorFunction.prototype.constructor`

创建实例对象的构造函数。对于 `GeneratorFunction` 实例，其初始值是 `GeneratorFunction` 构造函数。

`GeneratorFunction.prototype.prototype`

所有生成器函数共享同一个 `prototype` 属性，即 `Generator.prototype`。每个生成器函数实例也有自己的 `prototype` 属性。当生成器函数被调用时，返回的生成器对象从生成器函数继承 `prototype` 属性，而该属性又继承自 `GeneratorFunction.prototype.prototype`。

`GeneratorFunction.prototype[@@toStringTag]`

`@@toStringTag` 属性的初始值是字符串 `"GeneratorFunction"`。该属性被 `Object.prototype.toString()` 使用。

实例方法
----

*从其父类 `Function` 继承实例方法*。

规范
--

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

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

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

参见
--

* `function*`
* `function*` 表达式
* `Function`
* `AsyncFunction`
* `AsyncGeneratorFunction`
* 函数


parseInt - JavaScript

parseInt
========

**parseInt(*string*, *radix*)** 解析一个字符串并返回指定基数的十进制整数，`radix` 是 2-36 之间的整数，表示被解析字符串的基数。

尝试一下
----

语法
--
```

parseInt(string, radix);
```

### 参数

`string`

要被解析的值。如果参数不是一个字符串，则将其转换为字符串 (使用 `ToString`抽象操作)。字符串开头的空白符将会被忽略。

`radix`\_ 可选\_

从 `2` 到 `36` 的整数，表示进制的基数。例如指定 `16` 表示被解析值是十六进制数。如果超出这个范围，将返回 `NaN`。假如指定 `0` 或未指定，基数将会根据字符串的值进行推算。注意，推算的结果不会永远是默认值 `10`！文章后面的描述解释了当参数 `radix` 不传时该函数的具体行为。

### 返回值

从给定的字符串中解析出的一个整数。

或者 `NaN`，当

* `radix` 小于 `2` 或大于 `36`，或
* 第一个非空格字符不能转换为数字。
```

parseInt('123', 5) // 将'123'看作 5 进制数，返回十进制数 38 => 1*5^2 + 2*5^1 + 3*5^0 = 38
```

描述
--

`parseInt`函数将其第一个参数转换为一个字符串，对该字符串进行解析，然后返回一个整数或 `NaN`。

如果不是 `NaN`，返回值将是以第一个参数作为指定基数 radix 的转换后的十进制整数。(例如，`radix` 为 `10`，就是可以转换十进制数，为 `8` 可以转换八进制数 "07"，`16`可以转换十六进制数"0xff"，以此类推)。

对于 `radix` 为 `10` 以上的，英文字母表示大于 `9` 的数字。例如，对于十六进制数（基数 `16`），则使用 `A` 到 `F`。

如果 `parseInt` 遇到的字符不是指定 `radix` 参数中的数字，它将忽略该字符以及所有后续字符，并返回到该点为止已解析的整数值。`parseInt` 将数字截断为整数值。允许前导和尾随空格。

由于某些数字在其字符串表示形式中使用 e 字符（例如 `6.022×23` 表示 `6.022e23` ），因此当对非常大或非常小的数字使用数字时，使用 `parseInt` 截断数字将产生意外结果。`parseInt`不应替代 `Math.floor()`。

`parseInt` 可以理解两个符号。`+` 表示正数，`-` 表示负数（从 ECMAScript 1 开始）。它是在去掉空格后作为解析的初始步骤进行的。如果没有找到符号，算法将进入下一步；否则，它将删除符号，并对字符串的其余部分进行数字解析。

如果 `radix` 是 `undefined`、`0` 或未指定的，JavaScript 会假定以下情况：

1. 如果输入的 `string` 以 `0x` 或 `0X`（一个 0，后面是小写或大写的 X）开头，那么 radix 被假定为 16，字符串的其余部分被当做十六进制数去解析。
2. 如果输入的 `string` 以 "`0`"（0）开头，`radix` 被假定为 `8`（八进制）或 `10`（十进制）。具体选择哪一个 radix 取决于实现。ECMAScript 5 澄清了应该使用 10 (十进制)，但不是所有的浏览器都支持。**因此，在使用 `parseInt` 时，一定要指定一个 radix**。
3. 如果输入的 `string` 以任何其他值开头，`radix` 是 `10` (十进制)。

如果第一个字符不能转换为数字，`parseInt` 会返回 `NaN`。

为了算术的目的，`NaN` 值不能作为任何 `radix` 的数字。你可以调用 `isNaN` 函数来确定 `parseInt` 的结果是否为 `NaN`。如果将 NaN 传递给算术运算，则运算结果也将是 `NaN`。

要将一个数字转换为特定的 `radix` 中的字符串字段，请使用 `thatNumber.toString(radix)` 函数。

**警告：** `BigInt`。警告：`parseInt` 将 `BigInt` 转换为 `Number`，并在这个过程中失去了精度。这是因为拖尾的非数字值，包括 "n"，会被丢弃。

示例
--

### 示例：使用 `parseInt`

以下例子均返回`15`:

```js
parseInt("0xF", 16);
parseInt("F", 16);
parseInt("17", 8);
parseInt(021, 8);
parseInt("015", 10); // parseInt(015, 8); 返回 13
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); // 除了“0、1”外，其他数字都不是有效二进制数字
```

以下例子均返回 `-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); // 非常大的数值变成 4
parseInt(0.00000000000434, 10); // 非常小的数值变成 4
```

下面的例子返回 `224`

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

没有指定 `radix` 参数时的八进制解析
----------------------

尽管 ECMAScript 3 已经不赞成这种做法，且 ECMAScript 5 已经禁止了这种做法，但是仍然有很多实现环境仍然把以 0 开头的数值字符串（numeric string）解释为一个八进制数。下面的例子可能返回八进制的结果，也可能返回十进制的结果。**总是指定一个基数（radix）可以避免这种不可靠的行为。**

```js
parseInt("0e0");
// 0

parseInt("08");
// 0, '8' 不是八进制数字。
```

### ECMAScript 5 移除了八进制解析

ECMAScript 5 规范不再允许 `parseInt` 函数的实现环境把以 `0` 字符开始的字符串作为八进制数值。ECMAScript 5 陈述如下：

根据给定 radix，`parseInt`函数产生一个由字符串参数内容解析过来的整数值。字符串中开头的空白会被忽略。如果 radix 没有指定或者为 0，参数会被假定以 10 为基数来解析，如果数值以字符对 0x 或 0X 开头，会假定以 16 为基数来解析。

这与 ECMAScript 3 有所不同，ECMAScript 3 仅仅是不提倡这种做法但并没有禁止这种做法。

直至 2013 年，很多实现环境并没有采取新的规范所规定的做法，而且由于必须兼容旧版的浏览器，所以**永远都要明确给出 radix 参数的值。**

一个更严格的解析函数
----------

有时采用一个更严格的方法来解析整型值很有用。此时可以使用正则表达式：

```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()`
* `Number.parseFloat()`
* `Number.parseInt()`
* `isNaN()`
* `Number.toString()`
* `Object.valueOf`


Infinity - JavaScript

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`


eval() - JavaScript

eval()
======

**`eval()`** 函数会将传入的字符串当做 JavaScript 代码进行执行。

尝试一下
----

语法
--
```

eval(string)
```

### 参数

`string`

一个表示 JavaScript 表达式、语句或一系列语句的字符串。表达式可以包含变量与已存在对象的属性。

### 返回值

返回字符串中代码的返回值。如果返回值为空，则返回 `undefined`。

描述
--

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

`eval()` 的参数是一个字符串。如果字符串表示的是表达式，`eval()` 会对表达式进行求值。如果参数表示一个或多个 JavaScript 语句，那么`eval()` 就会执行这些语句。不需要用 `eval()` 来执行一个算术表达式：因为 JavaScript 可以自动为算术表达式求值。

如果你以字符串的形式构造了算术表达式，那么可以在后面用 `eval()`对它求值。例如，假设你有一个变量 `x`，你可以通过将表达式的字符串值（例如 `3 * x + 2`）赋值给一个变量，然后在你的代码后面的其他地方调用 `eval()`，来推迟涉及 `x` 的表达式的求值。

如果 `eval()` 的参数不是字符串， `eval()` 会将参数原封不动地返回。在下面的例子中，`String` 构造器被指定，而 `eval()` 返回了 `String` 对象而不是执行字符串。

```js
eval(new String("2 + 2")); // 返回了包含"2 + 2"的字符串对象
eval("2 + 2"); // returns 4
```

你可以使用一些通用的方法来绕过这个限制，例如使用 `toString()`。

```js
var expression = new String("2 + 2");
eval(expression.toString());
```

如果你间接的使用 `eval()`，比如通过一个引用来调用它，而不是直接的调用 `eval`。从 ECMAScript 5 起，它工作在全局作用域下，而不是局部作用域中。这就意味着，例如，下面的代码的作用声明创建一个全局函数，并且 `eval` 中的这些代码在执行期间不能在被调用的作用域中访问局部变量。

```js
function test() {
  var x = 2,
    y = 4;
  console.log(eval("x + y")); // 直接调用，使用本地作用域，结果是 6
  var geval = eval; // 等价于在全局作用域调用
  console.log(geval("x + y")); // 间接调用，使用全局作用域，throws ReferenceError 因为 `x` 未定义
  (0, eval)("x + y"); // 另一个间接调用的例子
}
```

永远不要使用 `eval`！
--------------

`eval()` 是一个危险的函数，它使用与调用者相同的权限执行代码。如果你用 `eval()` 运行的字符串代码被恶意方（不怀好意的人）修改，你最终可能会在你的网页/扩展程序的权限下，在用户计算机上运行恶意代码。更重要的是，第三方代码可以看到某一个 `eval()` 被调用时的作用域，这也有可能导致一些不同方式的攻击。相似的 `Function` 就不容易被攻击。

`eval()` 通常比其他替代方法更慢，因为它必须调用 JS 解释器，而许多其他结构则可被现代 JS 引擎进行优化。

此外，现代 JavaScript 解释器将 JavaScript 转换为机器代码。这意味着任何变量命名的概念都会被删除。因此，任意一个 eval 的使用都会强制浏览器进行冗长的变量名称查找，以确定变量在机器代码中的位置并设置其值。另外，新内容将会通过 `eval()` 引进给变量，比如更改该变量的类型，因此会强制浏览器重新执行所有已经生成的机器代码以进行补偿。但是（谢天谢地）存在一个非常好的 eval 替代方法：只需使用 window.Function。这有个例子方便你了解如何将`eval()`的使用转变为`Function()`。

使用 eval 的糟糕代码：

```js
function looseJsonParse(obj) {
  return eval("(" + obj + ")");
}
console.log(looseJsonParse("{a:(4-1), b:function(){}, c:new Date()}"));
```

不用 eval 的更好的代码：

```js
function looseJsonParse(obj) {
  return Function('"use strict";return (' + obj + ")")();
}
console.log(looseJsonParse("{a:(4-1), b:function(){}, c:new Date()}"));
```

比较上面的两个代码片段，两个代码片段似乎是以相同的方式工作，但再想一想：eval 的这个代码的速度要慢得多。注意`c: new Date()`在执行体中。在没有 eval 的函数中，对象在全局范围内被用来进行计算，因此浏览器可以放心的假设 `Date` 是来自 `window.Date` 的而不是一个名为 `Date` 的局部变量。然而，在使用 `eval()` 的代码中，浏览器不能假设这一点，因为如果你的代码是下面这个：

```js
function Date(n) {
  return [
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
    "Sunday",
  ][n % 7 || 0];
}
function looseJsonParse(obj) {
  return eval("(" + obj + ")");
}
console.log(looseJsonParse("{a:(4-1), b:function(){}, c:new Date()}"));
```

因此，在 `eval()` 版本的代码中，浏览器被迫进行高代价的查找调用以检查是否存在名为 `Date()` 的任何局部变量。与 `Function()` 相比，这是非常低效的。

在类似的情况下，如果你确实希望能够从 `Function()` 内部的代码调用 `Date` 函数，该怎么办？你应该躲避并退回到 `eval()` 吗？绝对不是，永远不要这么做。而是尝试下面的方法。

```js
function Date(n) {
  return [
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
    "Sunday",
  ][n % 7 || 0];
}
function runCodeWithDateFunction(obj) {
  return Function('"use strict";return (' + obj + ")")()(Date);
}
console.log(runCodeWithDateFunction("function(Date){ return Date(5) }"));
```

由于三重嵌套函数，上面的代码似乎效率低下，但让我们分析一下上述有效方法的好处：

1. 它使得传递给`runCodeWithDateFunction`的字符串中的代码更少；
2. 函数调用开销很小，使得代码尺寸小得多，值得获益；
3. `Function()`更容易让你的代码利用特性修饰 `"use strict"`；
4. 代码不使用 `eval()`，使其比其他方式快几个数量级。

最后，我们来看看简化版。使用如上所示的`Function()`，你可以更有效地缩小传递给`runCodeWithDateFunction`的代码字符串，因为函数参数名称也可以缩小，如下面的缩小代码所示。

```js
console.log(
  Function('"use strict";return(function(a){return a(5)})')()(function (a) {
    return "Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(
      " ",
    )[a % 7 || 0];
  }),
);
```

对于常见用例，`eval()`或`Function()`还有更安全 (而且更快！) 的替代方案。

### 访问成员属性

你不应该去使用 `eval()` 来将属性名字转化为属性。考虑下面的这个例子，被访问对象的属性在它被执行之前都会未知的。这里可以用 eval 处理：

```js
var obj = { a: 20, b: 30 };
var propName = getPropName(); // 返回 "a" 或 "b"

eval("var result = obj." + propsName);
```

但是，这里并不是必须得使用 `eval()`。事实上，这里并不建议这样使用。可以使用 属性访问器 进行代替，它更快、更安全：

```js
var obj = { a: 20, b: 30 };
var propName = getPropName(); // 返回 "a" 或 "b"
var result = obj[propName]; // obj[ "a" ] 与 obj.a 等价
```

你还可以使用这个方法去访问子代的属性。如下：

```js
var obj = { a: { b: { c: 0 } } };
var propPath = getPropPath(); // 例如返回 "a.b.c"

eval("var result = obj." + propPath);
```

这里，可以通过分割属性路径、循环遍历不同的属性，来避免 `eval()`：

```js
function getDescendantProp(obj, desc) {
  var arr = desc.split(".");
  while (arr.length) {
    obj = obj[arr.shift()];
  }
  return obj;
}

var obj = { a: { b: { c: 0 } } };
var propPath = getPropPath(); // 例如返回 "a.b.c"
var result = getDescendantProp(obj, propPath);
```

同样的方法也可实现设置子代的属性值：

```js
function setDescendantProp(obj, desc, value) {
  var arr = desc.split(".");
  while (arr.length > 1) {
    obj = obj[arr.shift()];
  }
  return (obj[arr[0]] = value);
}

var obj = { a: { b: { c: 0 } } };
var propPath = getPropPath(); // 例如，返回 "a.b.c"
var result = setDescendantProp(obj, propPath, 1); // a.b.c 值为 1
```

### 使用函数而非代码段

JavaScript 拥有 first-class functions，这意味着你可以将函数直接作为参数传递给其他接口，将他们保存在变量中或者对象的属性中，等等。很多 DOM 的 API 都用这种思路进行设计，你也可以（或者应该）这样子设计你的代码：

```js
// 代替 setTimeout(" ... ", 1000) 写法：
setTimeout(function() { ... }, 1000);

// 代替 elt.setAttribute("onclick", "...") 写法：
elt.addEventListener('click', function() { ... } , false);
```

闭包 也有助于创建参数化函数而不用连接字符串。

### 解析 JSON（将字符串转化为 JavaScript 对象）

如果你在调用 `eval()` 传入的字符串参数中包含数据（如：一个数组“[1,2,3]”）而不是代码，你应该考虑将其转换为 JSON 对象，这允许你用 JavaScript 语法的子集来表示数据。在扩展中下载 JSON 和 JavaScript

提示：因为 JSON 语法子集相对于 JavaScript 语法子集比较有局限性，很多在 JavaScript 中可用的特性在 JSON 中就不起作用了。比如，后缀逗号在 JSON 中不支持，并且对象中的属性名在 JSON 中必须用引号括起来。请务必使用 JSON 序列化方法来生成稍后将被解析为 JSON 的字符串。

### 尽量传递数据而非代码

例如，设计为抓取网页内容的扩展，可能会在 XPath 中定义抓取规则，而不是在 JavaScript 代码中。

### 以有限权限运行代码

如果你必须执行这段代码，应考虑以更低的权限运行。此建议主要适用于扩展和 XUL 应用程序，可以使用 Components.utils.evalInSandbox 做到降低权限。

示例
--

### 使用 `eval`

在下面的代码中，两种包含了 `eval()` 的声明都返回了 42。第一种是对字符串 "`x + y + 1`" 求值；第二种是对字符串 "`42`" 求值。

```js
var x = 2;
var y = 39;
var z = "42";
eval("x + y + 1"); // returns 42
eval(z); // returns 42
```

### 使用 `eval` 执行一串 JavaScript 语句

下面的例子使用 `eval()` 来执行 `str` 字符串。这个字符串包含了如果 `x` 等于 5，就打开一个 Alert 对话框并对 `z` 赋值 42，否则就对 `z` 赋值 0 的 JavaScript 语句。当第二个声明被执行，`eval()` 将会令字符串被执行，并最终返回赋值给 `z` 的 42。

```js
var x = 5;
var str = "if (x == 5) {console.log('z is 42'); z = 42;} else z = 0;";

console.log("z is ", eval(str));
```

如果你定义了多个值，则会返回最后一个值。

```js
var x = 5;
var str = "if (x == 5) {console.log('z is 42'); z = 42; x = 420; } else z = 0;";

console.log("x is ", eval(str)); // z is 42 x is 420
```

### 返回值

`eval` 返回最后一个表达式的值。

```js
var str = "if ( a ) { 1 + 1; } else { 1 + 2; }";
var a = true;
var b = eval(str); // returns 2

console.log("b is : " + b);

a = false;
b = eval(str); // returns 3

console.log("b is : " + b);
```

### `eval` 中函数作为字符串被定义需要“（”和“）”作为前缀和后缀

```js
var fctStr1 = "function a() {}";
var fctStr2 = "(function a() {})";
var fct1 = eval(fctStr1); // 返回 undefined
var fct2 = eval(fctStr2); // 返回一个函数
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-eval-x |

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

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

Firefox 相关
----------

* 从历史上看，`eval()` 有一个可选的第二个参数，指定上下文执行对象。这个参数是非标准的，并且明确地从 Firefox 4 中删除。请参阅 Firefox bug 531675。
参见
--

* 属性访问器
* WebExtension：在 content script 中使用 eval


TypedArray - JavaScript

TypedArray
==========

一个 ***TypedArray*** 对象描述了底层二进制数据缓冲区的类数组视图。没有称为 `TypedArray` 的全局属性，也没有直接可用的 `TypedArray` 构造函数。但是，有很多不同的全局属性，其值是指定元素类型的类型化数组构造函数，如下所列。在接下来的页面，你将找到可以与包含任意类型元素的任意类型化数组一起使用的常见属性和方法。

尝试一下
----

描述
--

`TypedArray` 构造函数（通常归类为 `%TypedArray%`，表示它的“内在性”，因为它与任何 JavaScript 程序暴露出的全局对象不对应）是所有 `TypedArray` 子类的通用父类。将 `%TypedArray%` 作为一个“抽象类”，其为所有类型化数组的子类提供了实用方法的通用接口。该构造函数没有直接暴露：没有全局的 `TypedArray` 属性。它只能通过`Object.getPrototypeOf(Int8Array)` 及类似方式访问。

当创建 `TypedArray` 子类（例如 `Int8Array`）的实例时，在内存的中会创建数组缓冲区，或者，如果将 `ArrayBuffer` 对象作为构造参数，则使用该 `ArrayBuffer`。缓冲区地址被保存为实例的内部属性并且所有的 `%TypedArray%.prototype` 方法都将基于数组缓冲区地址设置和获取值。

### TypedArray 对象

| 类型 | 值范围 | 字节大小 | 描述 | Web IDL 类型 | 等价的 C 类型 |
| --- | --- | --- | --- | --- | --- |
| `Int8Array` | -128 到 127 | 1 | 8 位有符号整型（补码） | `byte` | `int8_t` |
| `Uint8Array` | 0 到 255 | 1 | 8 位无符号整型 | `octet` | `uint8_t` |
| `Uint8ClampedArray` | 0 到 255 | 1 | 8 位无符号整型（一定在 0 到 255 之间） | `octet` | `uint8_t` |
| `Int16Array` | -32768 到 32767 | 2 | 16 位有符号整型（补码） | `short` | `int16_t` |
| `Uint16Array` | 0 到 65535 | 2 | 16 位无符号整型 | `unsigned short` | `uint16_t` |
| `Int32Array` | -2147483648 到 2147483647 | 4 | 32 位有符号整型（补码） | `long` | `int32_t` |
| `Uint32Array` | 0 到 4294967295 | 4 | 32 位无符号整型 | `unsigned long` | `uint32_t` |
| `Float32Array` | `-3.4E38` 到 `3.4E38` 并且 `1.2E-38` 是最小的正数 | 4 | 32 位 IEEE 浮点数（7 位有效数字，例如 `1.234567`） | `unrestricted float` | `float` |
| `Float64Array` | `-1.8E308` 到 `1.8E308` 并且 `5E-324` 是最小的正数 | 8 | 64 位 IEEE 浮点数（16 位有效数字，例如 `1.23456789012345`） | `unrestricted double` | `double` |
| `BigInt64Array` | -263 到 263 - 1 | 8 | 64 位有符号整型（补码） | `bigint` | `int64_t (signed long long)` |
| `BigUint64Array` (en-US) | 0 到 264 - 1 | 8 | 64 位无符号整型 | `bigint` | `uint64_t (unsigned long long)` |

### 值编码与标准化

所有的类型化数组都是基于 `ArrayBuffer` 进行操作的，你可以借此观察到每个元素的确切字节表示，因此二进制格式中的数字编码方式具有重要意义。

* 无符号整数数组（`Uint8Array`、`Uint16Array`、`Uint32Array` 和 `BigUint64Array`）直接以二进制形式存储数字。
* 有符号整数数组（`Int8Array`、`Int16Array`、`Int32Array` 和 `BigInt64Array`）使用二进制补码存储数字。
* 浮点数组（`Float32Array` 和 `Float64Array`）使用 IEEE 754浮点格式存储数字。`Number` 参考文档中有关于确切格式的更多信息。JavaScript 数字默认使用双精度浮点格式，这与 `Float64Array` 相同。`Float32Array` 将 23（而不是 52）位用于尾数，以及 8（而不是 11）位用于指数。请注意，规范要求所有的 `NaN` 值使用相同的位编码，但确切的位模式取决于实现。
* `Uint8ClampedArray` 是一种特殊情况。它像 `Uint8Array` 一样以二进制形式存储数字，但是当你存储超出范围的数字时，它会将数字*钳制*（clamp）到 0 到 255 的范围内，而不是截断最高有效位。

除了 `Int8Array`、`Unit8Array` 和 `Uint8ClampedArray` 以外的其他类型数组都将每个元素存储为多个字节。这些字节可以按照从最高有效位到最低有效位（大端序）或从最低有效位到最高有效位（小端序）的顺序进行排序。请参阅字节序以了解更多。类型化数组始终使用平台的本机字节顺序。如果要在缓冲区中写入和读取时指定字节顺序，应该使用 `DataView`。

当向这些类型化数组写入时，超出可表示范围的值将被标准化。

* 所有整数数组（`Uint8ClampedArray` 除外）都使用固定宽度数值转换，首先截断数字的小数部分，然后取最低位。
* `Uint8ClampedArray` 首先将数字钳制到 0 到 255 的范围内（大于 255 的值变为 255，小于 0 的值变为 0），然后使用银行家舍入法将结果*四舍五入*（而非向下取整）到最近的整数，也就是说，如果数字恰好在两个整数之间，它将四舍五入到最近的偶数。例如，`0.5` 变为 `0`，`1.5` 变为 `2`，`2.5` 变为 `2`。
* `Float32Array` 使用“银行家舍入法”将 64 位浮点数转换为 32 位。这与 `Math.fround()` 提供的算法相同。
### 底层为可变大小缓冲时的行为

当一个 `TypedArray` 被创建为一个可变大小缓冲的视图时，改变底层缓冲的大小会对 `TypedArray` 的大小产生不同的影响，这取决于 `TypedArray` 是否是长度跟踪的。

如果一个类型化数组是通过省略或传递 `undefined` 给第三个参数来创建的，那么它将*跟踪长度*，并且将自动调整大小以适应底层 `buffer` 的大小：

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const float32 = new Float32Array(buffer);

console.log(float32.byteLength); // 8
console.log(float32.length); // 2

buffer.resize(12);

console.log(float32.byteLength); // 12
console.log(float32.length); // 3
```

如果一个类型化数组是通过使用第三个 `length` 参数指定大小创建时，则它的大小不会随着 `buffer` 大小的增长而改变：

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const float32 = new Float32Array(buffer, 0, 2);

console.log(float32.byteLength); // 8
console.log(float32.length); // 2
console.log(float32[0]); // 0, 初始值

buffer.resize(12);

console.log(float32.byteLength); // 8
console.log(float32.length); // 2
console.log(float32[0]); // 0, 初始值
```

当 `buffer` 缩小时，其上的类型化数组可能会超出范围，在这种情况下，类型化数组的观测大小将减少为 0。这是非长度跟踪类型化数组唯一可能改变长度的情况。

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const float32 = new Float32Array(buffer, 0, 2);

buffer.resize(7);

console.log(float32.byteLength); // 0
console.log(float32.length); // 0
console.log(float32[0]); // undefined
```

如果你随后再次增长 `buffer` 以使类型化数组回到范围内，类型化数组的大小将恢复到其原始值。

```js
buffer.resize(8);

console.log(float32.byteLength); // 8
console.log(float32.length); // 2
console.log(float32[0]); // 0 - 又回到范围内了！
```

对于长度跟踪的类型化数组，如果 `buffer` 被缩小到小于 `byteOffset`，也会发生同样的事情。

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const float32 = new Float32Array(buffer, 4);
// float32 是长度跟踪的，但它只从第 4 个字节开始，直到缓冲的结尾，
// 所以如果缓冲被缩小到小于 4 个字节，类型化数组就将超出范围
buffer.resize(3);
console.log(float32.byteLength); // 0
```

构造函数
----

该对象不能被直接实例化——试图去使用 `new` 构造它将会抛出 `TypeError`。

```js
new (Object.getPrototypeOf(Int8Array))();
// TypeError: Abstract class TypedArray not directly constructable
```

但是，你可以使用一个指定的类型化数组创建实例，例如 `Int8Array` 或 `BigInt64Array`。这些对象的构造函数是通用的：

```js
new TypedArray()
new TypedArray(length)
new TypedArray(typedArray)
new TypedArray(object)

new TypedArray(buffer)
new TypedArray(buffer, byteOffset)
new TypedArray(buffer, byteOffset, length)
```

其中，`TypedArray` 是一个具体的构造函数。

**备注：** 所有 `TypedArray` 子类的构造函数只能使用 `new` 构造。试图在没有 `new` 的情况下调用，会抛出 `TypeError`。

### 参数

`typedArray`

当使用 `TypedArray` 子类的实例调用时，`typedArray` 会被拷贝到一个新的类型数组中。对于非 bigint `TypeedArray` 构造函数，`typedArray` 参数仅可以是非 bigint 类型（例如 `Int32Array`）。同样，对于 bigint `TypedArray` 构造函数（`BigInt64Array` 或 `BigUint64Array` (en-US)），`typedArray` 参数仅可以是 bigint 类型。`typedArray` 中的每个值在拷贝到新数组之前都转换为构造函数的相应类型。新的类型化数组的长度与 `typedArray` 参数的长度相同。

`object`

当使用的不是 `TypedArray` 实例的对象调用时，将以与 `TypedArray.from()` 方法相同的方式创建一个新的类型化数组。

`length` 可选

当使用非对象调用时，该参数将被视为指定类型化数组长度的数字。在内存中创建一个内部数组缓冲区，大小长度乘以 `BYTES_PER_ELEMENT` 字节，用 0 填充。省略所有参数，等同于使用 `0` 作为参数。

`buffer`、`byteOffset` 可选、`length` 可选

当使用 `ArrayBuffer` 或 `SharedArrayBuffer` 实例以及可选的 `byteOffset` 和 `length` 参数调用时，将创建一个新的指定缓冲区的类型化数组视图。`byteOffset` 和 `length` 参数指定类型化数组视图将暴露的内存范围。如果忽略这两个参数，则是整个视图的所有 `buffer`；如果仅忽略 `length`，则是从 `byteOffset` 开始的 `buffer` 剩余部分的视图。

### 异常

所有 `TypeArray` 子类构造函数都以相同的方式运行。它们都会抛出以下异常：

`TypeError`

抛出以下情况之一：

* 传递 `typedArray`，但它是 bigint 类型，而当前构造函数不是，反之亦然。
* 传递 `typedArray`，但它的缓冲区被分离了，或者直接传递分离了视图的 `buffer`。

`RangeError`

抛出以下情况之一：

* 新的类型化数组的长度太大。
* `buffer` 的长度（如果 `length` 参数没有指定）或 `byteOffset` 不是新的类型化数组元素大小的整数倍。
* `byteOffset` 不是有效的数组索引（0 和 253 - 1 之间的整数）。
* 当从一个缓冲区创建视图，边界在缓冲区之外。换句话说，`byteOffset + length * TypedArray.BYTES_PER_ELEMENT > buffer.byteLength`。

静态属性
----

这些属性定义在 `TypedArray` 构造函数中，因此由所有 `TypedArray` 子类型共享。

`get TypedArray[@@species]`

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

所有 `TypedArray` 子类也有着以下静态属性：

`TypedArray.BYTES_PER_ELEMENT`

返回不同的 `TypedArray` 对象元素字节数的数值。

静态方法
----

这些属性定义在 `TypedArray` 构造函数中，因此由所有 `TypedArray` 子类型共享。

`TypedArray.from()`

从类数组或者可迭代对象创建新的 `TypedArray`。参见 `Array.from()`。

`TypedArray.of()`

创建一个具有可变参数的 `TypedArray`。参见 `Array.of()`。

实例属性
----

这些属性都是在 `TypedArray` 属性对象上定义的访问器属性（getter），因此由所有 `TypedArray` 子类型共享。

`TypedArray.prototype.buffer`

返回类型化数组引用的 `ArrayBuffer`。

`TypedArray.prototype.byteLength`

返回类型化数组的长度（以字节为单位）。

`TypedArray.prototype.byteOffset`

返回从类型化数组距离 `ArrayBuffer` 起始位置的偏移量（以字节为单位）。

`TypedArray.prototype.length`

返回类型化数组中保存的元素个数。

所有 `TypedArray` 子类也有以下实例属性：

`TypedArray.prototype.BYTES_PER_ELEMENT`

返回不同的 `TypedArray` 对象元素大小的数字值。

实例方法
----

这些方法定义在 `TypedArray` 原型对象中，因此由所有 `TypedArray` 子类型共享。

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

返回给定索引处的数组元素。接受从最后一项往回计算的负整数。

`TypedArray.prototype.copyWithin()`

在数组内复制数组元素序列。参见 `Array.prototype.copyWithin()`。

`TypedArray.prototype.entries()`

返回一个新的*数组迭代器*对象，其中包含数组中每个索引的键/值对。参见 `Array.prototype.entries()`。

`TypedArray.prototype.every()`

如果调用数组中的每个元素都满足测试函数，则返回 `true`。参见 `Array.prototype.every()`。

`TypedArray.prototype.fill()`

用静态值填充数组中从开始索引到结束索引的所有元素。参见 `Array.prototype.fill()`。

`TypedArray.prototype.filter()`

返回一个新数组，其中包含调用所提供的筛选函数返回为 `true` 的所有数组元素。参见 `Array.prototype.filter()`。

`TypedArray.prototype.find()`

返回数组中满足提供的测试函数的第一个元素的值，如果没有找到合适的元素，则返回 `undefined`。参见 `Array.prototype.find()`。

`TypedArray.prototype.findIndex()`

返回数组中满足提供的测试函数的第一个元素的索引，如果没有找到合适的元素，则返回 `-1`。参见 `Array.prototype.findIndex()`。

`TypedArray.prototype.findLast()` (en-US)

回数组中满足提供的测试函数的最后一个元素的值，如果没有找到合适的元素，则返回 `undefined`。参见 `Array.prototype.findLast()`。

`TypedArray.prototype.findLastIndex()` (en-US)

返回数组中满足所提供测试函数的最后一个元素的索引，如果没有找到合适的元素，则返回 `-1`。参见 `Array.prototype.findLastIndex()`。

`TypedArray.prototype.forEach()`

对调用数组中的每个元素调用函数。参见 `Array.prototype.forEach()`。

`TypedArray.prototype.includes()`

根据类型化数组是否包含一个确定的元素，来决定返回 `true` 还是 `false` 参见 `Array.prototype.includes()`。

`TypedArray.prototype.indexOf()`

返回在调用数组中可以找到给定元素的第一个（最小）索引，如果没有找到，则返回 `-1`。参见 `Array.prototype.indexOf()`。

`TypedArray.prototype.join()`

将数组的所有元素连接为字符串。参见 `Array.prototype.join()`。

`TypedArray.prototype.keys()`

返回一个新的数组迭代器对象，该对象包含数组中每个索引的键。参见 `Array.prototype.keys()`。

`TypedArray.prototype.lastIndexOf()`

返回在调用数组中可以找到给定元素的最后一个（最大）索引，如果找不到，则返回 `-1`。参见 `Array.prototype.lastIndexOf()`。

`TypedArray.prototype.map()`

返回一个新数组，其中包含对调用数组中的每个元素调用函数的结果。参见 `Array.prototype.map()`。

`TypedArray.prototype.reduce()`

对数组的每个元素（从左到右）执行用户提供的“reducer”回调函数，将其简化为单个值。参见 `Array.prototype.reduce()`。

`TypedArray.prototype.reduceRight()`

对数组的每个元素（从右到左）执行用户提供的“reducer”回调函数，将其简化为单个值。参见 `Array.prototype.reduceRight()`。

`TypedArray.prototype.reverse()`

反转数组元素的顺序——第一个成为最后一个，最后一个成为第一个。参见 `Array.prototype.reverse()`。

`TypedArray.prototype.set()`

在类型化数组中存储多个值，从指定数组读取输入值。

`TypedArray.prototype.slice()`

提取调用数组的一部分并返回一个新数组。参见 `Array.prototype.slice()`。

`TypedArray.prototype.some()`

如果调用数组中至少有一个元素满足提供的测试函数，则返回 `true`。参见 `Array.prototype.some()`。

`TypedArray.prototype.sort()`

对数组的元素进行排序并返回该数组。参见 `Array.prototype.sort()`。

`TypedArray.prototype.subarray()`

从给定的开始和结束的元素索引返回一个新的 `TypedArray`。

`TypedArray.prototype.values()`

返回一个新的*数组迭代器*对象，该对象包含数组中每个索引的值。参见 `Array.prototype.values()`。

`TypedArray.prototype.toLocaleString()`

返回一个表示调用数组及其元素的本地化字符串。参见 `Array.prototype.toLocaleString()`。

`TypedArray.prototype.toString()`

返回一个表示调用数组及其元素的字符串。参见 `Array.prototype.toString()`。

`TypedArray.prototype[@@iterator]()`

返回一个新的*数组迭代器*对象，该对象包含数组中每个索引的值。

示例
--

### 访问属性

你可以使用标准数组索引语法（即使用括号符号）引用数组中的元素。但是，在类型数组上获取或设置索引属性不会在原型链中搜索此属性，即使索引已越界。索引属性将查询 `ArrayBuffer` 并且永远不会查看对象属性。你仍然可以使用命名属性，就像所有对象一样。

```js
// Setting and getting using standard array syntax
const int16 = new Int16Array(2);
int16[0] = 42;
console.log(int16[0]); // 42

// Indexed properties on prototypes are not consulted (Fx 25)
Int8Array.prototype[20] = "foo";
new Int8Array(32)[20]; // 0
// even when out of bound
Int8Array.prototype[20] = "foo";
new Int8Array(8)[20]; // undefined
// or with negative integers
Int8Array.prototype[-1] = "foo";
new Int8Array(8)[-1]; // undefined

// Named properties are allowed, though (Fx 30)
Int8Array.prototype.foo = "bar";
new Int8Array(32).foo; // "bar"
```

### 不能被冻结

不是空的 `TypedArray` 不能被冻结，因为它们的底层 `ArrayBuffer` 可以通过缓冲区的另一个 `TypedArray` 视图进行变化。这意味着对象将从不会真正地冻结。

```js
const i8 = Int8Array.of(1, 2, 3);
Object.freeze(i8);
// TypeError: Cannot freeze array buffer views with elements
```

### byteOffset 必须对齐

当将 `TypedArray` 构建为 `ArrayBuffer` 的视图时，`byteOffset` 参数必须与其元素大小对齐；换句话说，偏移量必须是 `BYTES_PER_ELEMENT` 的倍数。

```js
const i32 = new Int32Array(new ArrayBuffer(4), 1);
// RangeError: start offset of Int32Array should be a multiple of 4
```

```js
const i32 = new Int32Array(new ArrayBuffer(4), 0);
```

### byteLength 必须对齐

类似于 `byteOffset` 参数，`ArrayBuffer` 传递给 `TypedArray` 构造函数的 `byteLength` 属性必须是构造函数 `BYTES_PER_ELEMENT` 的倍数。

```js
const i32 = new Int32Array(new ArrayBuffer(3));
// RangeError: byte length of Int32Array should be a multiple of 4
```

```js
const i32 = new Int32Array(new ArrayBuffer(4));
```

规范
--

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

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

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

参见
--

* `core-js` 中类型化数组的 polyfill
* JavaScript 类型化数组
* `ArrayBuffer`
* `DataView`
* TextDecoder——从数字数据中解码字符串的助手


ArrayBuffer - JavaScript

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 - JavaScript

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 - JavaScript

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）


Error - JavaScript

Error
=====

当运行时错误产生时，`Error` 对象会被抛出。`Error` 对象也可用于用户自定义的异常的基础对象。下面列出了各种内建的标准错误类型。

描述
--

当代码运行时的发生错误，会创建新的 `Error` 对象，并将其抛出。

### 错误类型

除了通用的 `Error` 构造函数外，JavaScript 还有其他类型的错误构造函数。对于客户端异常，详见异常处理语句。

`EvalError`

创建一个 error 实例，表示错误的原因：与 `eval()` 有关。

`RangeError`

创建一个 error 实例，表示错误的原因：数值变量或参数超出其有效范围。

`ReferenceError`

创建一个 error 实例，表示错误的原因：无效引用。

`SyntaxError`

创建一个 error 实例，表示错误的原因：语法错误。

`TypeError`

创建一个 error 实例，表示错误的原因：变量或参数不属于有效类型。

`URIError`

创建一个 error 实例，表示错误的原因：给 `encodeURI()` 或 `decodeURI()` 传递的参数无效。

`AggregateError`

创建一个 error 实例，其中包裹了由一个操作产生且需要报告的多个错误。如：`Promise.any()` 产生的错误。

`InternalError`
非标准

创建一个代表 Javascript 引擎内部错误的异常抛出的实例。如：递归太多。

构造函数
----

`Error()`

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

静态方法
----

`Error.captureStackTrace()`
非标准

一个非标准的 V8 函数，用于在 Error 实例上创建 `stack` 属性。

`Error.stackTraceLimit`
非标准

一个非标准的 V8 数值属性，用于限制错误堆栈跟踪中包含堆栈帧数量。

`Error.prepareStackTrace()`
非标准
 可选

一个非标准的 V8 函数，如果提供了这一函数，V8 JavaScript 引擎会调用该函数来抛出异常。这个函数允许用户提供自定义的堆栈跟踪格式。

实例属性
----

`Error.prototype.message`

错误消息。对于用户创建的 `Error` 对象，这是构造函数的第一个参数提供的字符串。

`Error.prototype.name`

错误名称。这是由构造函数决定的。

`Error.prototype.cause`

表示导致当前错误被抛出的原因——通常是另一个错误。对于用户创建的 `Error` 对象，这是构造函数的第二个参数提供的值。

`Error.prototype.fileName`
非标准

一个非标准的 Mozilla 属性，用于表示引发此错误的文件的路径。

`Error.prototype.lineNumber`
非标准

一个非标准的 Mozilla 属性，用于表示引发此错误的代码所在的文件的行号。

`Error.prototype.columnNumber`
非标准

一个非标准的 Mozilla 属性，用于表示引发此错误的代码在文件中所在行的列号。

`Error.prototype.stack`
非标准

一个非标准的属性，用于堆栈跟踪。

实例方法
----

`Error.prototype.toString()`

返回表示该对象的字符串。覆盖了 `Object.prototype.toString()` 方法。

示例
--

### 抛出一个基本错误

通常你会使用 `throw` 关键字来抛出你创建的 `Error` 对象。可以使用 `try...catch` 结构来处理异常：

```js
try {
  throw new Error("Whoops!");
} catch (e) {
  console.error(e.name + ": " + e.message);
}
```

### 处理一个特定错误

你可以通过判断异常的类型来特定处理某一类的异常，即判断 `constructor` 属性，当使用现代 JavaScript 引擎时，可使用 `instanceof` 关键字：

```js
try {
  foo.bar();
} catch (e) {
  if (e instanceof EvalError) {
    console.error(e.name + ": " + e.message);
  } else if (e instanceof RangeError) {
    console.error(e.name + ": " + e.message);
  }
  // ... etc
  else {
    // If none of our cases matched leave the Error unhandled
    throw e;
  }
}
```

### 区分相似的错误

有时，对于代码块的错误需要根据其原因进行不同的处理，但错误的原因又较为相似（例如：错误的类型和消息均相同）。

如果你无法控制原有错误的抛出，那么一种方法是捕获错误然后抛出一个新的错误，并在新的错误中给出更加具体的错误消息。原始错误应该被传递到新的 `Error` 的构造函数的 `option` 参数（`cause` 属性）中，这确保了原始的错误和堆栈追踪信息在上层的 try/catch 块中可用。

以下示例展示了两种方法会在失败时抛出相似的错误（`doFailSomeWay()` 和 `doFailAnotherWay()`）：

```js
function doWork() {
  try {
    doFailSomeWay();
  } catch (err) {
    throw new Error("Failed in some way", { cause: err });
  }
  try {
    doFailAnotherWay();
  } catch (err) {
    throw new Error("Failed in another way", { cause: err });
  }
}

try {
  doWork();
} catch (err) {
  switch (err.message) {
    case "Failed in some way":
      handleFailSomeWay(err.cause);
      break;
    case "Failed in another way":
      handleFailAnotherWay(err.cause);
      break;
  }
}
```

**备注：** 如果你在创建一个函数库，你应该使用错误原因来区分不同的错误——而不是要求你的函数库的使用者来解析错误消息。相关的示例，请参见提供错误原因。

自定义错误类型也可以使用 `cause` 属性，前提是通过 `super()` 调用子类的构造函数时传递 `options` 参数。

```js
class MyError extends Error {
  constructor(/\* some arguments \*/) {
    // Needs to pass both `message` and `options` to install the "cause" property.
    super(message, options);
  }
}
```

### 自定义错误类型

你可能希望自定义基于 `Error` 的异常类型，使得你能够 `throw new MyError()` 并可以使用 `instanceof MyError` 来检查某个异常的类型。这种需求的通用解决方法如下。

参考 StackOverflow 上关于“What's a good way to extend Error in JavaScript?”的讨论。

#### ES6 自定义错误类

**警告：** Babel 7 之前的版本可以处理 `CustomError` 类方法，但类方法需要使用 Object.defineProperty() 定义。否则，旧版本的 Babel 和其他转译器在没有额外配置的情况下将无法正确处理下面的代码。

**备注：** 在使用 ES2015 的类时，一些浏览器会在堆栈跟踪中包含 `CustomError` 构造函数。

```js
class CustomError extends Error {
  constructor(foo = "bar", ...params) {
    // Pass remaining arguments (including vendor specific ones) to parent constructor
    super(...params);

    // Maintains proper stack trace for where our error was thrown (only available on V8)
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, CustomError);
    }

    this.name = "CustomError";
    // Custom debugging information
    this.foo = foo;
    this.date = new Date();
  }
}

try {
  throw new CustomError("baz", "bazMessage");
} catch (e) {
  console.error(e.name); // CustomError
  console.error(e.foo); // baz
  console.error(e.message); // bazMessage
  console.error(e.stack); // stacktrace
}
```

#### ES5 自定义错误对象

**警告：** 在使用原型声明时，所有浏览器都会在堆栈跟踪中包含 `CustomError` 的构造函数。

```js
function CustomError(foo, message, fileName, lineNumber) {
  var instance = new Error(message, fileName, lineNumber);
  instance.foo = foo;
  Object.setPrototypeOf(instance, CustomError.prototype);
  if (Error.captureStackTrace) {
    Error.captureStackTrace(instance, CustomError);
  }
  return instance;
}

Object.setPrototypeOf(CustomError.prototype, Error.prototype);

Object.setPrototypeOf(CustomError, Error);

CustomError.prototype.name = "CustomError";

try {
  throw new CustomError("baz", "bazMessage");
} catch (e) {
  console.error(e.name); // CustomError
  console.error(e.foo); // baz
  console.error(e.message); // bazMessage
}
```

规范
--

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

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

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

参见
--

* `core-js` 中提供了具有现代行为（如：支持 `cause`）的 `Error` 的 polyfill
* `throw`
* `try...catch`
* 关于 `Error.captureStackTrace()`、`Error.stackTraceLimit` 和 `Error.prepareStackTrace()` 的 V8 文档。


Iterator - JavaScript

Iterator
========

**`Iterator`** 对象是一个符合迭代器协议的对象，其提供了 `next()` 方法用以返回迭代器结果对象。所有内置迭代器都继承自 `Iterator` 类。`Iterator` 类提供了 `@@iterator` 方法，该方法返回迭代器对象本身，使迭代器也可迭代。它还提供了一些使用迭代器的辅助方法。

描述
--

以下都是内置的 JavaScript 迭代器：

* *数组迭代器*，返回自 `Array.prototype.values()`、`Array.prototype.keys()`、`Array.prototype.entries()`、`Array.prototype[@@iterator]()`、`TypedArray.prototype.values()`、`TypedArray.prototype.keys()`、`TypedArray.prototype.entries()`、`TypedArray.prototype[@@iterator]()` 和 `arguments[@@iterator]()`。
* *字符串迭代器*，返回自 `String.prototype[@@iterator]()`。
* *Map 迭代器*，返回自 `Map.prototype.values()`、`Map.prototype.keys()`、`Map.prototype.entries()` 和 `Map.prototype[@@iterator]()`。
* *Set 迭代器*，返回自 `Set.prototype.values()`、`Set.prototype.keys()`、`Set.prototype.entries()` 和 `Set.prototype[@@iterator]()`。
* *正则表达式字符串迭代器*，返回自 `RegExp.prototype[@@matchAll]()` 和 `String.prototype.matchAll()`。
* `Generator` 对象，返回自生成器函数。
* *Segment 迭代器*，返回自 `Intl.Segmenter.prototype.segment()` (en-US) 返回的 `Segments` (en-US) 对象的 `[@@iterator]()` (en-US) 方法。
* *迭代器辅助方法*，返回自迭代器辅助方法例如 `Iterator.prototype.filter()` (en-US) 和 `Iterator.prototype.map()` (en-US)。

每个迭代器都有一个不同的原型对象，它定义了特定迭代器使用的 `next()` 方法。例如，所有字符串迭代器对象都继承自隐藏对象 `StringIteratorPrototype`，该对象具有按码位迭代当前字符串的 `next()` 方法。`StringIteratorPrototype` 还有一个 `@@toStringTag` 属性，其初始值为字符串 `"String Iterator"`。该属性在 `Object.prototype.toString()` 中使用。类似地，其他迭代器原型也有自己的 `@@toStringTag` 值，这些值与上面给出的名称相同。

所有这些原型对象都继承自 `Iterator.prototype`，它提供了一个返回迭代器对象本身的 `@@iterator` 方法，这使迭代器也变得可迭代。

### 迭代器辅助方法

**备注：** 这些方法是*迭代器*辅助方法，而不是*可迭代对象*辅助方法，因为可迭代对象的唯一要求就是具有 `@@iterator` 方法，因此它们没有共享的原型来安装这些方法。

`Iterator` 类本身提供了一些使用迭代器的辅助方法。例如，你可能想做以下事情：

```js
const nameToDeposit = new Map([
  ["Anne", 1000],
  ["Bert", 1500],
  ["Carl", 2000],
]);

const totalDeposit = [...nameToDeposit.values()].reduce((a, b) => a + b);
```

这首先将 `Map.prototype.values()` 返回的迭代器器转换为数组，然后使用 `Array.prototype.reduce()` 方法计算总和。然而，这既创建了一个中间数组，又重复了数组两次。相反，你可以使用迭代器本身的 `reduce()` 方法：

```js
const totalDeposit = nameToDeposit.values().reduce((a, b) => a + b);
```

这种方法更加高效，因为它只迭代迭代器一次，而不需要保存任何中间值。迭代器辅助方法对于使用无限迭代器是必需的：

```js
function\* fibonacci() {
  let current = 1;
  let next = 1;
  while (true) {
    yield current;
    [current, next] = [next, current + next];
  }
}

const seq = fibonacci();
const firstThreeDigitTerm = seq.find((n) => n >= 100);
```

你无法将 `seq` 转换为数组，因为它是无穷的。相反，你可以使用迭代器本身的 `find()` 方法，该方法仅需要迭代 `seq` 查找满足条件的第一个值。

你会发现许多迭代器方法类似于数组方法，例如：

| 迭代器方法 | 数组方法 |
| --- | --- |
| `Iterator.prototype.every()` (en-US) | `Array.prototype.every()` |
| `Iterator.prototype.filter()` (en-US) | `Array.prototype.filter()` |
| `Iterator.prototype.find()` (en-US) | `Array.prototype.find()` |
| `Iterator.prototype.flatMap()` (en-US) | `Array.prototype.flatMap()` |
| `Iterator.prototype.forEach()` (en-US) | `Array.prototype.forEach()` |
| `Iterator.prototype.map()` (en-US) | `Array.prototype.map()` |
| `Iterator.prototype.reduce()` (en-US) | `Array.prototype.reduce()` |
| `Iterator.prototype.some()` (en-US) | `Array.prototype.some()` |

`Iterator.prototype.drop()` (en-US) 和 `Iterator.prototype.take()` (en-US) 组合起来有点类似于 `Array.prototype.slice()`。

在这些方法中，`filter()` (en-US)、`flatMap()` (en-US)、`map()` (en-US)、`drop()` (en-US) 和 `take()` (en-US) 返回一个新的*迭代器辅助方法*对象。迭代器辅助方法也是一个 `Iterator` 实例，使辅助方法可链式调用。所有迭代器辅助方法对象都继承了一个通用的原型对象，该对象实现了迭代器协议：

`next()`

调用底层迭代器的 `next()` 方法，将辅助方法应用于结果，并返回结果。

`return()`

调用底层迭代器的 `return()` 方法，并返回结果。

迭代器辅助方法与底层迭代器共享相同的数据源，因此迭代迭代器辅助方法会导致底层迭代器也被迭代。没有办法“复刻”迭代器以允许它被多次迭代。

```js
const it = [1, 2, 3].values();
const it2 = it.drop(0); // 本质上是一个副本
console.log(it.next().value); // 1
console.log(it2.next().value); // 2
console.log(it.next().value); // 3
```

### 恰当的迭代器

有两种“迭代器”：符合迭代器协议（必需且只需具有 `next()` 方法）的对象，以及继承自 `Iterator` 类的对象，后者可以使用辅助方法。两者互不包含——继承自 `Iterator` 的对象不会自动变成迭代器，因为 `Iterator` 类并未定义 `next()` 方法。相反，这些对象需要自己定义 `next()` 方法。*恰当的迭代器*指的是即符合迭代器协议，同时又继承自 `Iterator` 的迭代器。大多数代码所期望的迭代器都是恰当的迭代器并可以通过迭代返回恰当的迭代器。要创建恰当的迭代器，可以定义一个继承 `Iterator` (en-US) 的类，或使用 `Iterator.from()` (en-US) 方法。

```js
class MyIterator extends Iterator {
  next() {
    // …
  }
}

const myIterator = Iterator.from({
  next() {
    // …
  },
});
```

构造函数
----

* `Iterator()` (en-US)
实验性

    + ：旨在被创建迭代器的其他类继承。直接用于构建会抛出错误。
静态方法
----

`Iterator.from()` (en-US)
实验性

从一个迭代器或可迭代对象创建一个新的 `Iterator` 对象。

实例属性
----

这些属性定义于 `Iterator.prototype` 并由所有 `Iterator` 实例所共享。

`Iterator.prototype.constructor`

创建实例对象的构造函数。对于 `Iterator` 实例，其初始值是 `Iterator` (en-US) 构造函数。

`Iterator.prototype[@@toStringTag]`

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

**备注：** 与大多数内置类的 `@@toStringTag` 不同，出于 web 兼容性原因，`Iterator.prototype[@@toStringTag]` 是可写的。

实例方法
----

`Iterator.prototype.drop()` (en-US)
实验性

返回一个新的迭代器辅助方法，其会跳过当前迭代器开头给定数量的元素。

`Iterator.prototype.every()` (en-US)
实验性

测试是否所有由迭代器产生的元素都能通过由提供的函数实现的测试。

`Iterator.prototype.filter()` (en-US)
实验性

返回一个新的迭代器辅助方法，其只产生迭代器中令提供的回调函数返回 `true` 的那些元素。

`Iterator.prototype.find()` (en-US)
实验性

返回迭代器产生的第一个满足提供的测试函数的元素。如果没有满足测试函数的值，则返回 `undefined`。

`Iterator.prototype.flatMap()` (en-US)
实验性

返回一个新的迭代器辅助方法，其获取原始迭代器中的每个元素，通过映射函数进行映射，并产生映射函数返回的元素（包含在另一个迭代器或可迭代对象）。

`Iterator.prototype.forEach()` (en-US)
实验性

为迭代器生成的每个元素执行一次提供的函数。

`Iterator.prototype.map()` (en-US)
实验性

返回一个新的迭代器辅助方法，其生成的元素都由映射函数进行转换而来。

`Iterator.prototype.reduce()` (en-US)
实验性

对迭代器生成的每个元素执行用户提供的“reducer”回调函数，传入前一个元素计算的返回值。在所有元素上运行 reducer 的最终结果是单个值。

`Iterator.prototype.some()` (en-US)
实验性

测试迭代器中是否至少有一个能够的元素通过由提供的函数实现的测试。返回一个布尔值。

`Iterator.prototype.take()` (en-US)
实验性

返回一个新的迭代器帮助方法，它生成当前迭代器中给定数量的元素，然后结束。

`Iterator.prototype.toArray()` (en-US)
实验性

创建一个用迭代器产生的元素填充的新的 `Array` 实例。

`Iterator.prototype[@@iterator]()`

返回迭代器对象本身。这使迭代器对象也是可迭代的。

示例
--

### 使用迭代器作为可迭代对象

所有内置迭代器都是可迭代的，因此你可以在 `for...of` 循环中使用它们：

```js
const arrIterator = [1, 2, 3].values();
for (const value of arrIterator) {
  console.log(value);
}
// 打印：1, 2, 3
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-%iteratorprototype%-object |

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

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

参见
--

* `core-js` 中 `Iterator` 的 polyfill
* `function*`
* 迭代协议


isNaN() - JavaScript

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()`