Set - JavaScript

Set
===

**`Set`** 对象允许你存储任何类型（无论是原始值还是对象引用）的唯一值。

描述
--

`Set` 对象是值的合集（collection）。集合（set）中的元素**只会出现一次**，即集合中的元素是唯一的。你可以按照插入顺序迭代集合中的元素。*插入顺序*对应于 `add()` 方法成功将每一个元素插入到集合中（即，调用 `add()` 方法时集合中不存在相同的元素）的顺序。

规范要求集合的实现是“对合集中的元素的平均访问时间与集合中元素的数量呈次线性关系”。因此，它可以在内部表示为哈希表（查找的时间复杂度为 O(1)）、搜索树（查找的时间复杂度为 O(log(N))）或任何其他的时间复杂度低于 O(N) 的数据结构。

### 值的相等

值的相等是基于零值相等算法的。（曾使用会将 `0` 和 `-0` 视为不同值的同值算法。参见浏览器兼容性。）这意味着 `NaN` 和 `undefined` 会被视为是相同的值（即使 `NaN !== NaN`），而所有其他的值则基于 `===` 运算符的语义进行相等比较。

### 性能

`has` 方法检查某个值是否在集合中，其采用的方式的平均时间比逐个测试先前添加到集合中的元素更快。特别是当一个数组的长度（`length`）等于集合的大小（`size`）时，这比 `Array.prototype.includes` 方法的平均速度更快。

### 类 Set 浏览器 API

浏览器**类 `Set` 对象**（或“类集合对象”）是行为与 `Set` 类似的 Web API 接口。

就像 `Set` 一样，元素可以按照它们被添加到对象的顺序进行迭代。类 `Set` 对象也有与 `Set` 相同名称和行为的属性及方法。但是，与 `Set` 不同的是，前者只允许每个条目特定的预定义类型。

允许的类型由规范的 IDL 定义给出。例如，`GPUSupportedFeatures` (en-US) 是一个类 `Set` 对象，它必须以字符串为键/值。规范的 IDL 对其的定义如下：

```webidl
interface GPUSupportedFeatures {
  readonly setlike<DOMString>;
};
```

类 `Set` 对象是只读或可读写的（参见上面的 IDL 中的 `readonly` 关键字）。

* 只读的类 `Set` 对象具有 `size` 属性及以下方法：`entries()`、`forEach()`、`has()`、`keys()`、`values()` 和 `@@iterator`。
* 可写的类 `Set` 对象此外还具有以下方法：`clear()`、`delete()` 和 `add()`。

除了对条目类型的限制外，方法和属性的行为与 `Set` 中的等效成员相同。

以下是只读的类 `Set` 浏览器对象的示例：

* `GPUSupportedFeatures` (en-US)
* `XRAnchorSet` (en-US)

以下是可写的类 `Set` 浏览器对象的示例：

* `CustomStateSet` (en-US)
* `FontFaceSet`
* `Highlight` (en-US)
构造函数
----

`Set()`

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

静态属性
----

`Set[@@species]`

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

实例属性
----

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

`Set.prototype.constructor`

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

`Set.prototype.size`

返回 `Set` 对象中值的数量。

`Set.prototype[@@toStringTag]`

`@@toStringTag` 属性的初始值为字符串 `"Set"`。该属性用于 `Object.prototype.toString()`。

实例方法
----

`Set.prototype.add()`

如果 `Set` 中尚不存在具有相同值的元素，则在 `Set` 对象中插入一个新的具有指定值的元素。

`Set.prototype.clear()`

从 `Set` 对象中移除所有元素。

`Set.prototype.delete()`

移除与 `value` 关联的元素，并返回一个布尔值来表示是否移除成功。`Set.prototype.has(value)` 会在此之后返回 `false`。

`Set.prototype.entries()`

返回一个新的迭代器对象，该对象包含 `Set` 对象中的代表每个元素的 **`[value, value]` 数组**。这与 `Map` 对象类似，因此 `Set` 的每个条目的 *key* 和 *value* 都相同。

`Set.prototype.forEach()`

按照值插入的顺序为 `Set` 对象中的每个值调用一次 `callbackFn`。如果提供了 `thisArg` 参数，它将被用作每次调用 `callbackFn` 时的 `this` 值。

`Set.prototype.has()`

返回一个布尔值，表示给定值在 `Set` 对象中是否存在。

`Set.prototype.keys()`

`Set.prototype.values()` 的别名。

`Set.prototype.values()`

返回一个新的迭代器对象，该对象按插入顺序生成 `Set` 对象中每个元素的**值**。

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

返回一个新的迭代器对象，该对象按插入顺序生成 `Set` 对象中每个元素的**值**。

示例
--

### 使用 Set 对象

```js
const mySet1 = new Set();

mySet1.add(1); // Set(1) { 1 }
mySet1.add(5); // Set(2) { 1, 5 }
mySet1.add(5); // Set(2) { 1, 5 }
mySet1.add("some text"); // Set(3) { 1, 5, 'some text' }
const o = { a: 1, b: 2 };
mySet1.add(o);

mySet1.add({ a: 1, b: 2 }); // o 是不同对象的引用，所以这是可以的

mySet1.has(1); // true
mySet1.has(3); // false，因为并未将 3 添加到集合中
mySet1.has(5); // true
mySet1.has(Math.sqrt(25)); // true
mySet1.has("Some Text".toLowerCase()); // true
mySet1.has(o); // true

mySet1.size; // 5

mySet1.delete(5); // 从集合中移除 5
mySet1.has(5); // false，5 已从集合中移除

mySet1.size; // 4，因为我们刚刚移除了一个值

mySet1.add(5); // Set(5) { 1, 'some text', {...}, {...}, 5 }——先前删除的元素会作为新的元素被添加，不会保留删除前的原始位置

console.log(mySet1); // Set(5) { 1, "some text", {…}, {…}, 5 }
```

### 迭代集合

迭代会按元素的插入顺序访问集合中的元素。

```js
for (const item of mySet1) {
  console.log(item);
}
// 1、"some text"、{ "a": 1, "b": 2 }、{ "a": 1, "b": 2 }、5

for (const item of mySet1.keys()) {
  console.log(item);
}
// 1、"some text"、{ "a": 1, "b": 2 }、{ "a": 1, "b": 2 }、5

for (const item of mySet1.values()) {
  console.log(item);
}
// 1、"some text"、{ "a": 1, "b": 2 }、{ "a": 1, "b": 2 }、5

// 键和值是相同的
for (const [key, value] of mySet1.entries()) {
  console.log(key);
}
// 1、"some text"、{ "a": 1, "b": 2 }、{ "a": 1, "b": 2 }、5

// 使用 Array.from 将 Set 对象转换为数组对象
const myArr = Array.from(mySet1); // [1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}, 5]

// 如果在 HTML 文档中使用，也可以：
mySet1.add(document.body);
mySet1.has(document.querySelector("body")); // true

// 在 Set 和 Array 之间转换
const mySet2 = new Set([1, 2, 3, 4]);
console.log(mySet2.size); // 4
console.log([...mySet2]); // [1, 2, 3, 4]

// 可以通过如下代码模拟求交集
const intersection = new Set([...mySet1].filter((x) => mySet2.has(x)));

// 可以通过如下代码模拟求差集
const difference = new Set([...mySet1].filter((x) => !mySet2.has(x)));

// 使用 forEach() 迭代集合中的条目
mySet2.forEach((value) => {
  console.log(value);
});
// 1
// 2
// 3
// 4
```

### 实现基本集合操作

```js
function isSuperset(set, subset) {
  for (const elem of subset) {
    if (!set.has(elem)) {
      return false;
    }
  }
  return true;
}

function union(setA, setB) {
  const _union = new Set(setA);
  for (const elem of setB) {
    _union.add(elem);
  }
  return _union;
}

function intersection(setA, setB) {
  const _intersection = new Set();
  for (const elem of setB) {
    if (setA.has(elem)) {
      _intersection.add(elem);
    }
  }
  return _intersection;
}

function symmetricDifference(setA, setB) {
  const _difference = new Set(setA);
  for (const elem of setB) {
    if (_difference.has(elem)) {
      _difference.delete(elem);
    } else {
      _difference.add(elem);
    }
  }
  return _difference;
}

function difference(setA, setB) {
  const _difference = new Set(setA);
  for (const elem of setB) {
    _difference.delete(elem);
  }
  return _difference;
}

// 示例
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 3]);
const setC = new Set([3, 4, 5, 6]);

isSuperset(setA, setB); // 返回 true
union(setA, setC); // 返回 Set {1, 2, 3, 4, 5, 6}
intersection(setA, setC); // 返回 Set {3, 4}
symmetricDifference(setA, setC); // 返回 Set {1, 2, 5, 6}
difference(setA, setC); // 返回 Set {1, 2}
```

### 与数组的关系

```js
const myArray = ["value1", "value2", "value3"];

// 使用常规的 Set 构造函数将 Array 转换为 Set
const mySet = new Set(myArray);

mySet.has("value1"); // 返回 true

// 使用展开语法将 Set 转换为 Array。
console.log([...mySet]); // 将显示与 myArray 完全相同的数组
```

### 数组去重

```js
// 用于从数组中删除重复元素

const numbers = [2, 3, 4, 4, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 5, 32, 3, 4, 5];

console.log([...new Set(numbers)]);

// [2, 3, 4, 5, 6, 7, 32]
```

### 与字符串的关系

```js
const text = "India";

const mySet = new Set(text); // Set(5) {'I', 'n', 'd', 'i', 'a'}
mySet.size; // 5

// 大小写敏感，且忽略重复项
new Set("Firefox"); // Set(7) { "F", "i", "r", "e", "f", "o", "x" }
new Set("firefox"); // Set(6) { "f", "i", "r", "e", "o", "x" }
```

### 使用集合来确保一列值的唯一性

```js
const array = Array.from(document.querySelectorAll("[id]")).map((e) => e.id);

const set = new Set(array);
console.assert(set.size === array.length);
```

规范
--

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

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

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

参见
--

* `core-js` 中 `Set` 的 polyfill
* `Map`
* `WeakMap`
* `WeakSet`


AsyncIterator - JavaScript

AsyncIterator
=============

**`AsyncIterator`** 对象是符合异步迭代器协议的对象，其提供了 `next()` 方法用以返回一个兑现为迭代器结果对象的 promise。`AsyncIterator.prototype` 对象是一个隐藏的全局对象，所有内置的异步迭代器都继承自它。其提供了 `@@asyncIterator` 方法，该方法返回异步迭代器对象本身，使异步迭代器也异步可迭代。

注意，`AsyncIterator` *不是*全局对象，尽管将来会出现异步迭代器辅助方法提案。所有内置异步迭代器共享的 `AsyncIterator.prototype` 对象可以通过以下代码获得：

```js
const AsyncIteratorPrototype = Object.getPrototypeOf(
  Object.getPrototypeOf(Object.getPrototypeOf((async function\* () {})())),
);
```

描述
--

目前，唯一内置的 JavaScript 异步迭代器是由异步生成器函数返回的 `AsyncGenerator` 对象。还有一些其他的内置异步迭代器存在于 web API 中，例如 `ReadableStream` 的异步迭代器。

每个异步迭代器都有一个不同的原型对象，它定义了特定异步迭代器使用的 `next()` 方法。所有这些原型对象都继承自 `AsyncIterator.prototype`，它提供了一个 `@@asyncIterator` 方法，该方法返回异步迭代器对象本身，使异步迭代器也可异步迭代。

**备注：** `AsyncIterator.prototype` 并未实现 `@@iterator`，因此默认情况下，异步迭代器不是同步可迭代对象。

实例方法
----

`AsyncIterator.prototype[@@asyncIterator]()`

返回异步迭代器对象本身。这使异步迭代器对象也可以异步迭代。

示例
--

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

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

```js
const asyncIterator = (async function\* () {
  yield 1;
  yield 2;
  yield 3;
})();
(async () => {
  for await (const value of asyncIterator) {
    console.log(value);
  }
})();
// 输出：1，2，3
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-asynciteratorprototype |

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

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

参见
--

* `async function*`
* 迭代协议


InternalError - JavaScript

InternalError
=============

**非标准:** 该特性是非标准的，请尽量不要在生产环境中使用它！

**`InternalError` 对象**表示出现在 JavaScript 引擎内部的错误。通常描述某种数量过多的情况，例如：

* "too many switch cases"（过多 `case` 子句）；
* "too many parentheses in regular expression"（正则表达式中括号过多）；
* "array initializer too large"（数组初始化器过大）；
* "too much recursion"（递归过深）。
构造函数
----

`InternalError()` (en-US)
非标准

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

实例属性
----

`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`。

示例
--

### 递归过深

根据退出条件所述，以下递归函数运行 10 次。

```js
function loop(x) {
  // "x >= 10" 是退出条件
  if (x >= 10) return;

  // 做一些事情
  loop(x + 1); // 递归调用
}
loop(0);
```

如果这个条件值太高，可能不会奏效：

```js
function loop(x) {
  if (x >= 1000000000000) return;

  // 做一些事情
  loop(x + 1);
}
loop(0);

// InternalError: too much recursion
```

要获取更多信息，请参阅 InternalError: too much recursion。

规范
--

尚未成为任何规范的一部分。

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

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

参见
--

* `Error`
* InternalError: too much recursion


Proxy - JavaScript

Proxy
=====

**Proxy** 对象用于创建一个对象的代理，从而实现基本操作的拦截和自定义（如属性查找、赋值、枚举、函数调用等）。

术语
--

`handler` (en-US)

包含捕捉器（trap）的占位符对象，可译为处理器对象。

*traps*

提供属性访问的方法。这类似于操作系统中捕获器的概念。

*target*

被 Proxy 代理虚拟化的对象。它常被作为代理的存储后端。根据目标验证关于对象不可扩展性或不可配置属性的不变量（保持不变的语义）。

语法
--
```

const p = new Proxy(target, handler)
```

### 参数

`target`

要使用 `Proxy` 包装的目标对象（可以是任何类型的对象，包括原生数组，函数，甚至另一个代理）。

`handler`

一个通常以函数作为属性的对象，各属性中的函数分别定义了在执行各种操作时代理 `p` 的行为。

方法
--

`Proxy.revocable()`

创建一个可撤销的`Proxy`对象。

handler 对象的方法
-------------

`handler` 对象是一个容纳一批特定属性的占位符对象。它包含有 `Proxy` 的各个捕获器（trap）。

所有的捕捉器是可选的。如果没有定义某个捕捉器，那么就会保留源对象的默认行为。

`handler.getPrototypeOf()`

`Object.getPrototypeOf` 方法的捕捉器。

`handler.setPrototypeOf()`

`Object.setPrototypeOf` 方法的捕捉器。

`handler.isExtensible()`

`Object.isExtensible` 方法的捕捉器。

`handler.preventExtensions()`

`Object.preventExtensions` 方法的捕捉器。

`handler.getOwnPropertyDescriptor()`

`Object.getOwnPropertyDescriptor` 方法的捕捉器。

`handler.defineProperty()`

`Object.defineProperty` 方法的捕捉器。

`handler.has()`

`in` 操作符的捕捉器。

`handler.get()`

属性读取操作的捕捉器。

`handler.set()`

属性设置操作的捕捉器。

`handler.deleteProperty()`

`delete` 操作符的捕捉器。

`handler.ownKeys()`

`Object.getOwnPropertyNames` 方法和 `Object.getOwnPropertySymbols` 方法的捕捉器。

`handler.apply()`

函数调用操作的捕捉器。

`handler.construct()`

`new` 操作符的捕捉器。

一些不标准的捕捉器已经被废弃并且移除了。

示例
--

### 基础示例

在以下简单的例子中，当对象中不存在属性名时，默认返回值为 `37`。下面的代码以此展示了 `get` handler 的使用场景。

```js
const handler = {
  get: function (obj, prop) {
    return prop in obj ? obj[prop] : 37;
  },
};

const p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;

console.log(p.a, p.b); // 1, undefined
console.log("c" in p, p.c); // false, 37
```

### 无操作转发代理

在以下例子中，我们使用了一个原生 JavaScript 对象，代理会将所有应用到它的操作转发到这个对象上。

```js
let target = {};
let p = new Proxy(target, {});

p.a = 37; // 操作转发到目标

console.log(target.a); // 37. 操作已经被正确地转发
```

### 验证

通过代理，你可以轻松地验证向一个对象的传值。下面的代码借此展示了 `set` handler 的作用。

```js
let validator = {
  set: function (obj, prop, value) {
    if (prop === "age") {
      if (!Number.isInteger(value)) {
        throw new TypeError("The age is not an integer");
      }
      if (value > 200) {
        throw new RangeError("The age seems invalid");
      }
    }

    // The default behavior to store the value
    obj[prop] = value;

    // 表示成功
    return true;
  },
};

let person = new Proxy({}, validator);

person.age = 100;

console.log(person.age);
// 100

person.age = "young";
// 抛出异常：Uncaught TypeError: The age is not an integer

person.age = 300;
// 抛出异常：Uncaught RangeError: The age seems invalid
```

### 扩展构造函数

方法代理可以轻松地通过一个新构造函数来扩展一个已有的构造函数。这个例子使用了`construct`和`apply`。

```js
function extend(sup, base) {
  var descriptor = Object.getOwnPropertyDescriptor(
    base.prototype,
    "constructor",
  );
  base.prototype = Object.create(sup.prototype);
  var handler = {
    construct: function (target, args) {
      var obj = Object.create(base.prototype);
      this.apply(target, obj, args);
      return obj;
    },
    apply: function (target, that, args) {
      sup.apply(that, args);
      base.apply(that, args);
    },
  };
  var proxy = new Proxy(base, handler);
  descriptor.value = proxy;
  Object.defineProperty(base.prototype, "constructor", descriptor);
  return proxy;
}

var Person = function (name) {
  this.name = name;
};

var Boy = extend(Person, function (name, age) {
  this.age = age;
});

Boy.prototype.sex = "M";

var Peter = new Boy("Peter", 13);
console.log(Peter.sex); // "M"
console.log(Peter.name); // "Peter"
console.log(Peter.age); // 13
```

### 操作 DOM 节点

有时，我们可能需要互换两个不同的元素的属性或类名。下面的代码以此为目标，展示了 `set` handler 的使用场景。

```js
let view = new Proxy(
  {
    selected: null,
  },
  {
    set: function (obj, prop, newval) {
      let oldval = obj[prop];

      if (prop === "selected") {
        if (oldval) {
          oldval.setAttribute("aria-selected", "false");
        }
        if (newval) {
          newval.setAttribute("aria-selected", "true");
        }
      }

      // 默认行为是存储被传入 setter 函数的属性值
      obj[prop] = newval;

      // 表示操作成功
      return true;
    },
  },
);

let i1 = (view.selected = document.getElementById("item-1"));
console.log(i1.getAttribute("aria-selected")); // 'true'

let i2 = (view.selected = document.getElementById("item-2"));
console.log(i1.getAttribute("aria-selected")); // 'false'
console.log(i2.getAttribute("aria-selected")); // 'true'
```

### 值修正及附加属性

以下`products`代理会计算传值并根据需要转换为数组。这个代理对象同时支持一个叫做 `latestBrowser`的附加属性，这个属性可以同时作为 getter 和 setter。

```js
let products = new Proxy(
  {
    browsers: ["Internet Explorer", "Netscape"],
  },
  {
    get: function (obj, prop) {
      // 附加一个属性
      if (prop === "latestBrowser") {
        return obj.browsers[obj.browsers.length - 1];
      }

      // 默认行为是返回属性值
      return obj[prop];
    },
    set: function (obj, prop, value) {
      // 附加属性
      if (prop === "latestBrowser") {
        obj.browsers.push(value);
        return;
      }

      // 如果不是数组，则进行转换
      if (typeof value === "string") {
        value = [value];
      }

      // 默认行为是保存属性值
      obj[prop] = value;

      // 表示成功
      return true;
    },
  },
);

console.log(products.browsers); // ['Internet Explorer', 'Netscape']
products.browsers = "Firefox"; // 如果不小心传入了一个字符串
console.log(products.browsers); // ['Firefox'] <- 也没问题，得到的依旧是一个数组

products.latestBrowser = "Chrome";
console.log(products.browsers); // ['Firefox', 'Chrome']
console.log(products.latestBrowser); // 'Chrome'
```

### 通过属性查找数组中的特定对象

以下代理为数组扩展了一些实用工具。如你所见，通过 Proxy，我们可以灵活地“定义”属性，而不需要使用 `Object.defineProperties` 方法。以下例子可以用于通过单元格来查找表格中的一行。在这种情况下，target 是 `table.rows` (en-US)。

```js
let products = new Proxy(
  [
    { name: "Firefox", type: "browser" },
    { name: "SeaMonkey", type: "browser" },
    { name: "Thunderbird", type: "mailer" },
  ],
  {
    get: function (obj, prop) {
      // 默认行为是返回属性值，prop ?通常是一个整数
      if (prop in obj) {
        return obj[prop];
      }

      // 获取 products 的 number; 它是 products.length 的别名
      if (prop === "number") {
        return obj.length;
      }

      let result,
        types = {};

      for (let product of obj) {
        if (product.name === prop) {
          result = product;
        }
        if (types[product.type]) {
          types[product.type].push(product);
        } else {
          types[product.type] = [product];
        }
      }

      // 通过 name 获取 product
      if (result) {
        return result;
      }

      // 通过 type 获取 products
      if (prop in types) {
        return types[prop];
      }

      // 获取 product type
      if (prop === "types") {
        return Object.keys(types);
      }

      return undefined;
    },
  },
);

console.log(products[0]); // { name: 'Firefox', type: 'browser' }
console.log(products["Firefox"]); // { name: 'Firefox', type: 'browser' }
console.log(products["Chrome"]); // undefined
console.log(products.browser); // [{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }]
console.log(products.types); // ['browser', 'mailer']
console.log(products.number); // 3
```

### 一个完整的 `traps` 列表示例

出于教学目的，这里为了创建一个完整的 traps 列表示例，我们将尝试代理化一个非原生对象，这特别适用于这类操作：由 发布在 document.cookie 页面上的“小型框架” (en-US)创建的`docCookies`全局对象。

```js
/\*
 var docCookies = ... get the "docCookies" object here:
 https://developer.mozilla.org/zh-CN/docs/DOM/document.cookie#A\_little\_framework.3A\_a\_complete\_cookies\_reader.2Fwriter\_with\_full\_unicode\_support
\*/

var docCookies = new Proxy(docCookies, {
  get: function (oTarget, sKey) {
    return oTarget[sKey] || oTarget.getItem(sKey) || undefined;
  },
  set: function (oTarget, sKey, vValue) {
    if (sKey in oTarget) {
      return false;
    }
    return oTarget.setItem(sKey, vValue);
  },
  deleteProperty: function (oTarget, sKey) {
    if (sKey in oTarget) {
      return false;
    }
    return oTarget.removeItem(sKey);
  },
  enumerate: function (oTarget, sKey) {
    return oTarget.keys();
  },
  ownKeys: function (oTarget, sKey) {
    return oTarget.keys();
  },
  has: function (oTarget, sKey) {
    return sKey in oTarget || oTarget.hasItem(sKey);
  },
  defineProperty: function (oTarget, sKey, oDesc) {
    if (oDesc && "value" in oDesc) {
      oTarget.setItem(sKey, oDesc.value);
    }
    return oTarget;
  },
  getOwnPropertyDescriptor: function (oTarget, sKey) {
    var vValue = oTarget.getItem(sKey);
    return vValue
      ? {
          value: vValue,
          writable: true,
          enumerable: true,
          configurable: false,
        }
      : undefined;
  },
});

/\* Cookies 测试 \*/

alert((docCookies.my_cookie1 = "First value"));
alert(docCookies.getItem("my\_cookie1"));

docCookies.setItem("my\_cookie1", "Changed value");
alert(docCookies.my_cookie1);
```

规范
--

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

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

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

参考
--

* "Proxies are awesome" Brendan Eich presentation at JSConf (slides)
* ECMAScript Harmony Proxy proposal page and ECMAScript Harmony proxy semantics page
* Tutorial on proxies
* SpiderMonkey specific Old Proxy API
* `Object.watch()` is a non-standard feature but has been supported in Gecko for a long time.
版权声明
----

一些内容（如文本、例子）是复制自或修改自ECMAScript wiki（版权声明 CC 2.0 BY-NC-SA）。


EvalError - JavaScript

EvalError
=========

本对象代表了一个关于 `eval()` 全局函数的错误。此异常不再会被 JavaScript 抛出，但是 EvalError 对象仍然存在，以保持兼容性。

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

构造函数
----

`EvalError()` (en-US)

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

实例属性
----

`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`。

示例
--

`EvalError` 不在当前的 ECMAScript 规范中使用，因此不会被运行时抛出。但是对象本身仍然与规范的早期版本向后兼容。

### 创建 EvalError

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

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

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

参见
--

* `Error`
* `eval()`


decodeURI() - JavaScript

decodeURI()
===========

**`decodeURI()`** 函数能解码由`encodeURI` 创建或其他流程得到的统一资源标识符（URI）。

尝试一下
----

语法
--
```

decodeURI(encodedURI)
```

### 参数

`encodedURI`

一个完整的编码过的 URI

### 返回值

返回一个给定编码统一资源标识符 (URI) 的未编码版本的新字符串。

### 异常

当`encodedURI` 包含无效字符序列时，引发`URIError`（“格式错误的 URI 序列”）异常。

描述
--

将已编码 URI 中所有能识别的转义序列转换成原字符，但不能解码那些不会被 `encodeURI` 编码的内容（例如 "`#`"）。

示例
--

### 解码一个西里尔字母（Cyrillic）URL

```js
decodeURI(
  "https://developer.mozilla.org/ru/docs/JavaScript\_%D1%88%D0%B5%D0%BB%D0%BB%D1%8B",
);
// "https://developer.mozilla.org/ru/docs/JavaScript\_шеллы"
```

### 捕捉异常
```

try {
  var a = decodeURI('%E0%A4%A');
} catch(e) {
  console.error(e);
}

// URIError: malformed URI sequence
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-decodeuri-encodeduri |

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

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

参见
--

* `decodeURIComponent`
* `encodeURI`
* `encodeURIComponent`


Boolean - JavaScript

Boolean
=======

**`Boolean`** 对象是一个布尔值的对象包装器。

描述
--

如果需要，作为第一个参数传递的值将转换为布尔值。如果省略该参数或参数值为 `0`、`-0`、`null`、`false`、`NaN`、`undefined`，或空字符串（`""`），则该对象具有的初始值为 `false`。所有其他值，包括任何对象，空数组（`[]`）或字符串 `"false"`，都会创建一个初始值为 `true` 的对象。

注意不要将基本类型中的布尔值 `true` 和 `false` 与值为 `true` 和 `false` 的 `Boolean` 对象弄混了。

其值不是 `undefined` 或 `null` 的任何对象（包括其值为 `false` 的布尔对象）在传递给条件语句时都将计算为 `true`。例如，以下 `if` 语句中的条件评估为 `true`：

```js
const x = new Boolean(false);
if (x) {
  // 这里的代码会被执行
}
```

基本类型的布尔值不受此规则影响。例如下面的 `if` 语句的条件为假：

```js
const x = false;
if (x) {
  // 这里的代码不会执行
}
```

不要用创建 `Boolean` 对象的方式将一个非布尔值转化成布尔值，直接将 `Boolean` 当做转换函数来使用即可，或者使用双重非（!!）运算符：

```js
const x = Boolean(expression); // use this...
const x = !!expression; // ...or this
const x = new Boolean(expression); // don't use this!
```

对于任何对象，即使是值为 `false` 的 `Boolean` 对象，当将其传给 `Boolean` 函数时，生成的 `Boolean` 对象的值都是 `true`。

```js
const myFalse = new Boolean(false); // initial value of false
const g = Boolean(myFalse); // initial value of true
const myString = new String("Hello"); // string object
const s = Boolean(myString); // initial value of true
```

最后，不要在应该使用基本类型布尔值的地方使用 `Boolean` 对象。

**备注：** 当将非标准属性 `document.all` 用作此构造函数的参数时，结果是值为 `false` 的布尔对象。此属性是旧的、非标准的属性，不应使用。

当使用非严格相等（`==`）来比较一个对象和布尔原始值时，最重要的是需要弄明白最终比较的是什么。请看一下的示例：

```js
if ([]) {
  console.log("[] is truthy"); // logs "[] is truthy"
}
if ([] == false) {
  console.log("[] == false"); // logs "[] == false"
}
```

`[]` 是真值而 `[] == false` 也同时成立的原因是：非严格比较 `[] == false` 会将 `[]` 的原始值和 `false` 进行比较。而获取 `[]` 的原始值时，JavaScript 引擎会首先调用 `[].toString()`。其结果为 `""`，也是最终和 `false` 一起比较的值。换句话说，`[] == false` 等价于 `"" == false`，而 `""` 是假值——这也解释了为什么会得到这一结果。

构造函数
----

`Boolean()`

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

实例方法
----

`Boolean.prototype.toString()`

根据对象的值返回字符串 `true` 或 `false`。覆盖了 `Object.prototype.toString()` 方法。

`Boolean.prototype.valueOf()`

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

示例
--

### 以初始值 `false` 创建 `Boolean` 对象

```js
const bNoParam = new Boolean();
const bZero = new Boolean(0);
const bNull = new Boolean(null);
const bEmptyString = new Boolean("");
const bfalse = new Boolean(false);
```

### 以初始值 `true` 创建 `Boolean` 对象

```js
const btrue = new Boolean(true);
const btrueString = new Boolean("true");
const bfalseString = new Boolean("false");
const bSuLin = new Boolean("Su Lin");
const bArrayProto = new Boolean([]);
const bObjProto = new Boolean({});
```

规范
--

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

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

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

参见
--

* Boolean
* 基本类型：布尔类型
* 布尔类型（维基百科）


WeakSet - JavaScript

WeakSet
=======

**`WeakSet`** 是可被垃圾回收的值的集合，包括对象和非全局注册的符号。`WeakSet` 中的值只能出现一次。它在 `WeakSet` 的集合中是唯一的。

描述
--

WeakSet 中的值一定是可被垃圾回收的值。大多数原始数据类型可以被任意地创建，并且没有生命周期，所以它们不能被存储。对象和非全局注册的符号可以被存储，因为它们是可被垃圾回收的值。

它和 `Set` 对象的主要区别有：

* `WeakSet` **只能是对象和符号**的集合，它不能像 `Set` 那样包含任何类型的任意值。
* `WeakSet` 持*弱引用*：`WeakSet` 中对象的引用为*弱*引用。如果没有其他的对 `WeakSet` 中对象的引用存在，那么这些对象会被垃圾回收。

**备注：** 这也意味着集合中没有存储当前值的列表。`WeakSet` 是不可枚举的。
### 用例：检测循环引用

递归调用自身的函数需要一种通过跟踪哪些对象已被处理，来应对循环数据结构的方法。

为此，`WeakSet` 非常适合处理这种情况：

```js
// 对传入的 subject 对象内部存储的所有内容执行回调
function execRecursively(fn, subject, _refs = new WeakSet()) {
  // 避免无限递归
  if (_refs.has(subject)) {
    return;
  }

  fn(subject);
  if (typeof subject === "object") {
    _refs.add(subject);
    for (const key in subject) {
      execRecursively(fn, subject[key], _refs);
    }
  }
}

const foo = {
  foo: "Foo",
  bar: {
    bar: "Bar",
  },
};

foo.bar.baz = foo; // 循环引用！
execRecursively((obj) => console.log(obj), foo);
```

在此，在第一次运行时创建 `WeakSet`，并将其与每个后续函数调用一起传递（使用内部参数 `_refs`）。

对象的数量或它们的遍历顺序无关紧要，因此，`WeakSet` 比 `Set` 更适合（和执行）跟踪对象引用，尤其是在涉及大量对象时。

构造函数
----

`WeakSet()`

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

实例属性
----

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

`WeakSet.prototype.constructor`

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

`WeakSet.prototype[@@toStringTag]`

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

实例方法
----

`WeakSet.prototype.add()`

将 `value` 追加到 `WeakSet` 对象。

`WeakSet.prototype.delete()`

从 `WeakSet` 中移除 `value`。此后调用 `WeakSet.prototype.has(value)` 将返回 `false`。

`WeakSet.prototype.has()`

返回一个表示 `value` 是否存在于 `WeakSet` 对象中的布尔值。

示例
--

### 使用 WeakSet 对象

```js
const ws = new WeakSet();
const foo = {};
const bar = {};

ws.add(foo);
ws.add(bar);

ws.has(foo); // true
ws.has(bar); // true

ws.delete(foo); // 从 set 中删除 foo 对象
ws.has(foo); // false，foo 对象已经被删除了
ws.has(bar); // true，bar 依然存在
```

注意，`foo !== bar`。尽管它们是相似的对象，*但是它们不是**同一个对象***。因此，它们都可以被加入到集合中。

规范
--

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

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

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

参见
--

* `core-js` 中 `WeakSet` 的 Polyfill
* `Map`
* `Set`
* `WeakMap`


String - JavaScript

String
======

**`String`** 对象用于表示和操作字符序列。

描述
--

字符串对于保存可以以文本形式表示的数据很有用。一些最常用的字符串操作是检查它们的长度，使用 + 和 += 字符串运算符来构建和连接它们，使用 `indexOf()` 方法检查子字符串的存在或者位置，或使用 `substring()` 方法提取子字符串。

### 创建字符串

字符串可以通过字符串字面量创建为原始值，也可以通过 `String()` 构造函数创建为字符串对象：

```js
const string1 = "A string primitive";
const string2 = 'Also a string primitive';
const string3 = `Yet another string primitive`;
```

```js
const string4 = new String("A String object");
```

字符串原始值和字符串对象共享很多行为，但也有其他重要的区别和注意事项。请参阅下面的“字符串原始值和字符串对象”。

字符串字面量可以使用单引号或者双引号指定，它们的处理方式相同，或者使用反引号字符 ```。最后一种形式指定了模板字符串，你可以在其中插入表达式。有关字符串字面量语法的更多信息，请参见词法语法。

### 访问字符

有两种方式访问字符串中的单个字符。首先是 `charAt()` 方法：

```js
"cat".charAt(1); // gives value "a"
```

另一个方式是将字符串视为类数组对象，其中各个字符对应于一个数字索引：

```js
"cat"[1]; // gives value "a"
```

当使用方括号表示法进行字符串访问时，尝试删除或为其复制的行为将不成功。涉及的属性既不可写（writable）也不可配置（configurable）（更多细节，请参见 `Object.defineProperty()`）。

### 比较字符串

使用小于和大于运算符来比较字符串：

```js
const a = "a";
const b = "b";
if (a < b) {
  // true
  console.log(`${a} 小于 ${b}`);
} else if (a > b) {
  console.log(`${a} 大于 ${b}`);
} else {
  console.log(`${a} 和 ${b} 相等`);
}
```

注意，所有的比较运算符（包括 `===` 和 `==`）在比较字符串时都区分大小写。不区分大小写地比较字符串的常见方式是在比较它们之前将它们转为相同的大小写（大写或者小写）。

```js
function areEqualCaseInsensitive(str1, str2) {
  return str1.toUpperCase() === str2.toUpperCase();
}
```

通过 `toUpperCase()` 或 `toLowerCase()` 进行转换的选择大多是任意的，并且在扩展到拉丁字母之外时，两者都不是完全可靠的。例如，德语小写字母 `ß` 和 `ss` 都被 `toUpperCase()` 转换为 `SS`，而土耳其字母 `ı` 会被 `toLowerCase()` 错误地报告为不等于 `I`，除非使用 `toLocaleLowerCase("tr")`。

```js
const areEqualInUpperCase = (str1, str2) =>
  str1.toUpperCase() === str2.toUpperCase();
const areEqualInLowerCase = (str1, str2) =>
  str1.toLowerCase() === str2.toLowerCase();

areEqualInUpperCase("ß", "ss"); // true；应该为 false
areEqualInLowerCase("ı", "I"); // false；应该为 true
```

用于测试不区分大小写的相等性的本地化（locale-aware）且可靠的解决方案是使用 `Intl.Collator` API 或者字符串的 `localeCompare()` 方法——它们共享相同的接口——`sensitivity` 选项设置为 `"accent"` 或 `"base"`。

```js
const areEqual = (str1, str2, locale = "en-US") =>
  str1.localeCompare(str2, locale, { sensitivity: "accent" }) === 0;

areEqual("ß", "ss", "de"); // false
areEqual("ı", "I", "tr"); // true
```

`localeCompare()` 方法使字符串比较可以像 `strcmp()` 函数一样进行——它允许以本地化的方式对字符串进行排序。

### 字符串原始值和字符串对象

注意，JavaScript 区分 `String` 对象和原始字符串值（`Boolean` 和 `Number` 也是如此）。

字符串字面量（使用单引号或者双引号表示）和从非构造函数上下文中的 `String` 调用返回的字符串（即在不使用 `new` 关键字的情况下调用）是原始字符串。在需要调用原始字符串的方法或进行属性查找的上下文中，JavaScript 将自动包装原始字符串并在包装对象上调用方法或执行属性查找。

```js
const strPrim = "foo"; // 字面量是一个字符串原始值
const strPrim2 = String(1); // 被强制转换为字符串原始值“1”
const strPrim3 = String(true); // 被强制转换为字符串原始值“true”
const strObj = new String(strPrim); // 使用 `new` 关键字调用 `String` 构造函数返回一个字符串包装对象。

console.log(typeof strPrim); // "string"
console.log(typeof strPrim2); // "string"
console.log(typeof strPrim3); // "string"
console.log(typeof strObj); // "object"
```

**警告：** 你应该基本不会将 `String` 作为构造函数使用。

使用 `eval()` 时，字符串原始值和 `String` 对象也会给出不同的结果。传递给 `eval` 的原始值被当作源代码处理；而 `String` 对象则被当作对象处理，返回对象。例如：

```js
const s1 = "2 + 2"; // 创建一个字符串原始值
const s2 = new String("2 + 2"); // 创建一个 String 对象
console.log(eval(s1)); // 返回数字 4
console.log(eval(s2)); // 返回字符串“2 + 2”
```

因此，当一段代码在期望使用字符串原始值的时候却使用了 `String` 对象是，可能会导致执行失败，虽然一般情况下，我们并不需要考虑这样的问题。

`String` 对象始终可以使用 `valueOf()` 方法将其转换为对应的原始值。

```js
console.log(eval(s2.valueOf())); // 返回数字 4
```

### 字符串强制转换

许多内置操作首先将它们的参数强制转换为字符串（这就是为什么 `String` 对象的行为类似于字符串原始值的原因）。这些操作可以总结为以下几点：

* 字符串按原样返回。
* `undefined` 转换成 `"undefined"`。
* `null` 转换成 `"null"`。
* `true` 转换成 `"true"`；`false` 转换成 `"false"`。
* 使用与 `toString(10)` 相同的算法转换数字。
* 使用与 `toString(10)` 相同的算法转换 BigInt。
* Symbol 抛出 `TypeError`。
* 对于对象，首先，通过依次调用其 `[@@toPrimitive]()`（hint 为 `"string"`）、`toString()` 和 `valueOf()` 方法将其转换为原始值。然后将生成的原始值转换为一个字符串。

有几种方法可以在 JavaScript 中实现几乎相同的效果。

* 模板字符串：``${x}`` 为嵌入的表达式执行上面的字符串强制转换步骤。
* `String()` 函数：`String(x)` 使用相同的算法去转换 `x`，只是 Symbol 不会抛出 `TypeError`，而是返回 `"Symbol(description)"`，其中 `description` 是对 Symbol 的描述。
* 使用 `+` 运算符：`"" + x` 将其操作数强制转为*原始值*，而不是*字符串*，并且对于某些对象，其行为与普通字符串强制转换完全不同。有关更多细节，请参见其参考页。

根据你使用的情况，你可能想要使用 ``${x}``（模拟内置行为）或 `String(x)`（处理 symbol 值而不抛出错误），但你不应该使用 `"" + x`。

### UTF-16 字符、Unicode 码位和字素簇

字符串基本上表示为 UTF-16 码元的序列。在 UTF-16 编码中，每个码元都是 16 位长。这意味着最多有 216 个或 65536 个可能的字符可表示为单个 UTF-16 码元。该字符集称为基本多语言平面（BMP），包含最常见的字符，如拉丁字母、希腊字母、西里尔字母以及许多东亚字符。每个码元都可以用以 `\u` 开头的 4 个十六进制数字写在一个字符串中。

然而，整个 Unicode 字符集比 65536 大得多。额外的字符以*代理对*（surrogate pair）的形式存储在 UTF-16 中，代理对是一对 16 位码元，表示一个单个字符。为了避免起义，配对的两个部分必须介于 `0xD800` 和 `0xDFFF` 之间，并且这些码元不用于编码单码元字符。（更准确地说，前导代理，也称为高位代理，其值在 `0xD800` 和 `0xDBFF` 之间（含），而后尾代理，也称为低位代理，其值在 `0xDC00` 和 `0xDFFF` 之间（含）。）每个 Unicode 字符由一个或者两个 UTF-16 码元组成，也称为 *Unicode 码位*（code point）。每个 Unicode 码位都可以使用 `\u{xxxxxx}` 写成一个字符串，其中 `xxxxxx` 表示 1–6 个十六进制数字。

“单独代理项（lone surrogate）”是指满足以下描述之一的 16 位码元：

* 它在范围 `0xD800` 到 `0xDBFF` 内（含）（即为前导代理），但它是字符串中的最后一个码元，或者下一个码元不是后尾代理。
* 它在范围 `0xDC00` 到 `0xDFFF` 内（含）（即为后尾代理），但它是字符串中的第一个码元，或者前一个码元不是前导代理。

单独代理项不代表任何 Unicode 字符。尽管大多数 JavaScript 内置方法都可以正确处理它们，因为它们都是基于 UTF-16 码元工作的，但是在与其他系统交互时，单独代理项通常不是有效的值。例如，`encodeURI()` 会为单独代理项抛出 `URIError`，因为 URI 编码使用 UTF-8 编码，而 UTF-8 没有任何编码单独代理项的方法。不包含任何单独代理项的字符串称为*规范的*字符串，并且可以安全地与不处理 UTF-16 的函数一起使用，例如 `encodeURI()` 或 `TextEncoder` 。你可以使用 `isWellFormed()` 方法检查字符串是否规范，或使用 `toWellFormed()` 方法清除单独代理项。

除了 Unicode 字符之外，还有某些 Unicode 字符序列应视为一个视觉单元，被称为*字素簇*（grapheme cluster）。最常见的情况是 emoji：许多具有多种变体的 emoji 实际上是由多个 emoji 组成的，通常由 <ZWJ>（`U+200D`）字符连接。

你必须小心迭代字符级别。例如，`split("")` 将按照 UTF-16 码元分割并将代理对分开。字符串索引也是指的每个 UTF-16 码元的索引。另一方面，`@@iterator()` 按 Unicode 码位迭代。遍历字素簇将需要一些自定义代码。

```js
"😄".split(""); // ['\ud83d', '\ude04']; splits into two lone surrogates

// "Backhand Index Pointing Right: Dark Skin Tone"
[..."👉🏿"]; // ['👉', '🏿']
// splits into the basic "Backhand Index Pointing Right" emoji and
// the "Dark skin tone" emoji

// "Family: Man, Boy"
[..."👨👦"]; // [ '👨', '', '👦' ]
// splits into the "Man" and "Boy" emoji, joined by a ZWJ

// The United Nations flag
[..."🇺🇳"]; // [ '🇺', '🇳' ]
// splits into two "region indicator" letters "U" and "N".
// All flag emojis are formed by joining two region indicator letters
```

构造函数
----

`String()`

创建一个新的 `String` 对象。它在作为函数调用时执行类型转换，而不是作为构造函数调用，后者通常更有用。

静态方法
----

`String.fromCharCode()`

返回使用指定的 Unicode 值序列创建的字符串。

`String.fromCodePoint()`

返回使用指定的码位序列创建的字符串。

`String.raw()`

返回从原始模板字符串创建的字符串。

实例属性
----

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

`String.prototype.constructor`

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

这些属性是每个 `String` 实例的自有属性。

`String.prototype.length`

反映字符串的 `length`。只读。

实例方法
----

`String.prototype.at()`

返回指定索引处的字符（正好是一个 UTF-16 码元）。接受负整数，从最后一个字符串字符开始倒数。

`String.prototype.charAt()`

返回指定 `index` 处的字符（正好是一个 UTF-16 码元）。

`String.prototype.charCodeAt()`

返回一个数字，它是给定 `index` 处的 UTF-16 码元值。

`String.prototype.codePointAt()`

返回一个非负整数值，它是从指定位置（`pos`）开始的 UTF-16 编码码位的码位值。

`String.prototype.concat()`

合并两个（或更多）字符串的文本并返回一个新字符串。

`String.prototype.endsWith()`

确定字符串是否以字符串 `searchString` 的字符结尾。

`String.prototype.includes()`

确定调用字符串是否包含 `searchString`。

`String.prototype.indexOf()`

返回在调用 `String` 对象中第一次出现的 `searchValue` 的索引，如果未找到则返回 `-1`。

`String.prototype.isWellFormed()`

返回一个布尔值，指示此字符串是否包含任何单独代理项。

`String.prototype.lastIndexOf()`

返回在调用 `String` 对象中最后一次出现的 `searchValue` 的索引，如果未找到则返回 `-1`。

`String.prototype.localeCompare()`

返回一个数字，用于指示一个参考字符串 `compareString` 是否在排序顺序前面或之后或与给定字符串相同。

`String.prototype.match()`

用于将正则表达式 `regexp` 与字符串匹配。

`String.prototype.matchAll()`

返回所有 `regexp` 的匹配项的迭代器。

`String.prototype.normalize()`

返回调用字符串值的 Unicode 规范化形式。

`String.prototype.padEnd()`

用给定字符串从末尾填充当前字符串并返回长度为 `targetLength` 的新字符串。

`String.prototype.padStart()`

用给定字符串从开头填充当前字符串并返回长度为 `targetLength` 的新字符串。

`String.prototype.repeat()`

返回由对象的元素重复 `count` 次组成的字符串。

`String.prototype.replace()`

用于使用 `replaceWith` 替换出现的 `searchFor`。`searchFor` 可以是字符串或正则表达式，`replaceWith` 可以是字符串或函数。

`String.prototype.replaceAll()`

用于使用 `replaceWith` 替换所有出现的 `searchFor`。`searchFor` 可以是字符串或正则表达式，`replaceWith` 可以是字符串或函数。

`String.prototype.search()`

搜索正则表达式 `regexp` 和调用字符串之间的匹配项。

`String.prototype.slice()`

提取字符串的一部分并返回一个新字符串。

`String.prototype.split()`

返回一个由在出现子字符串 `sep` 时拆分调用的字符串然后填充的字符串数组。

`String.prototype.startsWith()`

确定调用字符串是否以字符串 `searchString` 的字符开头。

`String.prototype.substring()`

返回一个新字符串，其中包含来自（或之间）指定索引（或多个索引）的调用字符串的字符。

`String.prototype.toLocaleLowerCase()`

字符串中的字符将转换为小写，同时尊重当前语言环境。

对于大多数语言，这将返回与 `toLowerCase()` 相同的结果。

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

字符串中的字符将转换为大写，同时尊重当前语言环境。

对于大多数语言，这将返回与 `toUpperCase()` 相同的结果。

`String.prototype.toLowerCase()`

返回转换为小写的调用字符串值。

`String.prototype.toString()`

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

`String.prototype.toUpperCase()`

返回转换为大写的调用字符串值。

`String.prototype.toWellFormed()`

返回一个字符串，其中包含的所有单独代理项都替换为 Unicode 替换字符 U+FFFD。

`String.prototype.trim()`

修剪字符串开头和结尾的空格。

`String.prototype.trimEnd()`

修剪字符串结尾的空格。

`String.prototype.trimStart()`

修剪字符串开头的空格。

`String.prototype.valueOf()`

返回指定对象的原始值。重写 `Object.prototype.valueOf()` 方法。

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

返回一个新的迭代器对象，该对象迭代 String 值的码位，将每个码位作为 String 值返回。

HTML 包装器方法
----------

**警告：** 已弃用。请避免使用这些方法。

它们的用途有限，因为它们基于非常古老的 HTML 标准并且仅提供当前可用的 HTML 标记和属性的一个子集。现在已经为它们创建了已弃用或非标准的标记。此外，它们在没有任何验证或清理的情况下进行简单的字符串连接，这使得它们在使用 `innerHTML` 直接插入时成为潜在的安全威胁。请改用 DOM API，例如 `document.createElement()`。

`String.prototype.anchor()`
已弃用

`<a name="name">`（超文本目标）

`String.prototype.big()`
已弃用

`<big>`
`String.prototype.blink()`
已弃用

`<blink>`

`String.prototype.bold()`
已弃用

`<b>`
`String.prototype.fixed()`
已弃用

`<tt>`
`String.prototype.fontcolor()`
已弃用

`<font color="color">`

`String.prototype.fontsize()`
已弃用

`<font size="size">`

`String.prototype.italics()`
已弃用

`<i>`
`String.prototype.link()`
已弃用

`<a href="url">`（链接 URL）

`String.prototype.small()`
已弃用

`<small>`
`String.prototype.strike()`
已弃用

`<strike>`
`String.prototype.sub()`
已弃用

`<sub>`
`String.prototype.sup()`
已弃用

`<sup>`

请注意，这些方法不会检查字符串本身是否包含 HTML 标记，因此可能会创建无效的 HTML：

```js
"".bold(); //
```

它们所做的唯一转义是将属性值中的 `"`（例如 `anchor()`、`fontcolor()`、`fontsize()` 和 `link()`）替换为 `"`。

```js
"foo".anchor('"Hello"'); // foo
```

示例
--

### 字符串转换

可以使用 `String` 作为 `toString()` 更可靠的代替方法，因为它在用于 `null` 和 `undefined` 时仍然有效。例如：

```js
const nullVar = null;
nullVar.toString(); // TypeError: nullVar is null
String(nullVar); // "null"

const undefinedVar = undefined;
undefinedVar.toString(); // TypeError: undefinedVar is undefined
String(undefinedVar); // "undefined"
```

规范
--

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

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

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

参见
--

* JavaScript 指南中的文本格式化
* `RegExp`


SyntaxError - JavaScript

SyntaxError
===========

**`SyntaxError`**（语法错误）对象代表尝试解析不符合语法的代码的错误。当 Javascript 引擎解析代码时，遇到了不符合语法规范的标记（token）或标记顺序，则会抛出 `SyntaxError`。

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

构造函数
----

`SyntaxError()` (en-US)

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

实例属性
----

`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`。

示例
--

### 捕获 SyntaxError

```js
try {
  eval("hoo bar");
} catch (e) {
  console.error(e instanceof SyntaxError);
  console.error(e.message);
  console.error(e.name);
  console.error(e.fileName);
  console.error(e.lineNumber);
  console.error(e.columnNumber);
  console.error(e.stack);
}
```

### 创建 SyntaxError

```js
try {
  throw new SyntaxError("Hello", "someFile.js", 10);
} catch (e) {
  console.error(e instanceof SyntaxError); // true
  console.error(e.message); // Hello
  console.error(e.name); // SyntaxError
  console.error(e.fileName); // someFile.js
  console.error(e.lineNumber); // 10
  console.error(e.columnNumber); // 0
  console.error(e.stack); // @debugger eval code:3:9
}
```

规范
--

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

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

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

参见
--

* `Error`


AsyncGeneratorFunction - JavaScript

AsyncGeneratorFunction
======================

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

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

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

`AsyncGeneratorFunction` 是 `Function` 的一个子类。

尝试一下
----

构造函数
----

`AsyncGeneratorFunction()`

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

实例属性
----

*同时也从它的父类 `Function` 继承实例属性*。

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

`AsyncGeneratorFunction.prototype.constructor`

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

`AsyncGeneratorFunction.prototype.prototype`

所有异步生成器函数共享相同的 `prototype` 属性，即 `AsyncGenerator.prototype`。每个异步生成器函数实例也都有它自己的 `prototype` 属性。当调用异步生成器函数时，返回的异步生成器对象继承自异步生成器函数的 `prototype` 属性，而 property 属性也继承自 `AsyncGeneratorFunction.prototype.prototype`。

`AsyncGeneratorFunction.prototype[@@toStringTag]`

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

实例方法
----

*同时也从它的父类 `Function` 继承方法*。

规范
--

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

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

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

参见
--

* `async function*`
* `async function*` 表达式
* `Function`
* `AsyncFunction`
* `GeneratorFunction`
* 函数


Reflect - JavaScript

Reflect
=======

**Reflect** 是一个内置的对象，它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US) 的方法相同。`Reflect` 不是一个函数对象，因此它是不可构造的。

描述
--

与大多数全局对象不同 `Reflect` 并非一个构造函数，所以不能通过 new 运算符对其进行调用，或者将 `Reflect` 对象作为一个函数来调用。`Reflect` 的所有属性和方法都是静态的（就像 `Math` 对象）。

`Reflect` 对象提供了以下静态方法，这些方法与 proxy handler 方法的命名相同。

静态方法
----

`Reflect.apply(target, thisArgument, argumentsList)`

对一个函数进行调用操作，同时可以传入一个数组作为调用参数。和 `Function.prototype.apply()` 功能类似。

`Reflect.construct(target, argumentsList[, newTarget])`

对构造函数进行 `new` 操作，相当于执行 `new target(...args)`。

`Reflect.defineProperty(target, propertyKey, attributes)`

和 `Object.defineProperty()` 类似。如果设置成功就会返回 `true`

`Reflect.deleteProperty(target, propertyKey)`

作为函数的`delete`操作符，相当于执行 `delete target[name]`。

`Reflect.get(target, propertyKey[, receiver])`

获取对象身上某个属性的值，类似于 `target[name]`。

`Reflect.getOwnPropertyDescriptor(target, propertyKey)`

类似于 `Object.getOwnPropertyDescriptor()`。如果对象中存在该属性，则返回对应的属性描述符，否则返回 `undefined`。

`Reflect.getPrototypeOf(target)`

类似于 `Object.getPrototypeOf()`。

`Reflect.has(target, propertyKey)`

判断一个对象是否存在某个属性，和 `in` 运算符 的功能完全相同。

`Reflect.isExtensible(target)`

类似于 `Object.isExtensible()`.

`Reflect.ownKeys(target)`

返回一个包含所有自身属性（不包含继承属性）的数组。(类似于 `Object.keys()`, 但不会受`enumerable` 影响).

`Reflect.preventExtensions(target)`

类似于 `Object.preventExtensions()`。返回一个`Boolean`。

`Reflect.set(target, propertyKey, value[, receiver])`

将值分配给属性的函数。返回一个`Boolean`，如果更新成功，则返回`true`。

`Reflect.setPrototypeOf(target, prototype)`

设置对象原型的函数。返回一个 `Boolean`，如果更新成功，则返回 `true`。

Examples
--------

### 检测一个对象是否存在特定属性
```

const duck = {
  name: 'Maurice',
  color: 'white',
  greeting: function() {
    console.log(`Quaaaack! My name is ${this.name}`);
  }
}

Reflect.has(duck, 'color');
// true
Reflect.has(duck, 'haircut');
// false
```

### 返回这个对象自身的属性
```

Reflect.ownKeys(duck);
// [ "name", "color", "greeting" ]
```

### 为这个对象添加一个新的属性
```

Reflect.set(duck, 'eyes', 'black');
// returns "true" if successful
// "duck" now contains the property "eyes: 'black'"
```

规范
--

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

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

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

参见
--

* `Proxy`


AsyncGenerator - JavaScript

AsyncGenerator
==============

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

异步生成器方法总是产生 `Promise` 对象。

`AsyncGenerator` 是隐藏类 `AsyncIterator` 的子类。

尝试一下
----

构造函数
----

`AsyncGenerator` 构造函数并非全局可用的。`AsyncGenerator` 的实例必须从异步生成器函数返回。

```js
async function\* createAsyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
  yield await Promise.resolve(3);
}
const asyncGen = createAsyncGenerator();
asyncGen.next().then((res) => console.log(res.value)); // 1
asyncGen.next().then((res) => console.log(res.value)); // 2
asyncGen.next().then((res) => console.log(res.value)); // 3
```

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

实例属性
----

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

`AsyncGenerator.prototype.constructor`

用于创建实例对象的构造函数。对于 `AsyncGenerator` 实例，初始值是 `AsyncGeneratorFunction.prototype`。

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

`AsyncGenerator.prototype[@@toStringTag]`

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

实例方法
----

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

`AsyncGenerator.prototype.next()`

返回 `Promise`，它将通过 `yield` 表达式产生的给定值兑现。

`AsyncGenerator.prototype.return()`

就好像在生成器的暂停位置插入一个 `return` 语句，这将结束生成器并允许生成器执行任何清理任务，尤其是与 `try...finally` 块结合的时候。

`AsyncGenerator.prototype.throw()`

就好像在生成器的暂停位置插入一个 `throw` 语句，这将通知生成器错误的状况并允许去处理错误，或者执行清理操作并关闭它自己。

示例
--

### 迭代异步生成器

以下示例将遍历迭代异步生成器，以递减的时间间隔将值 1-6 打印到控制台。注意，每次产生 Promise 的时候，它会在 `for await...of` 循环中自动地兑现。

```js
// 异步任务。假设它在实践中做了一些更有用的事情。
function delayedValue(time, value) {
  return new Promise((resolve /\*, reject\*/) => {
    setTimeout(() => resolve(value), time);
  });
}

async function\* generate() {
  yield delayedValue(2000, 1);
  yield delayedValue(100, 2);
  yield delayedValue(500, 3);
  yield delayedValue(250, 4);
  yield delayedValue(125, 5);
  yield delayedValue(50, 6);
  console.log("全部完成！");
}

async function main() {
  for await (const value of generate()) {
    console.log("值", value);
  }
}

main().catch((e) => console.error(e));
```

规范
--

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

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

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

参见
--

* function\*
* async function\*
* `function*` 表达式
* 生成器函数
* 异步生成器函数
* 迭代器和生成器指南


encodeURIComponent() - JavaScript

encodeURIComponent()
====================

**`encodeURIComponent()`** 函数通过将特定字符的每个实例替换成代表字符的 UTF-8 编码的一个、两个、三个或四个转义序列来编码 URI（只有由两个“代理”字符组成的字符会被编码为四个转义序列）。与 `encodeURI()` 相比，此函数会编码更多的字符，包括 URI 语法的一部分。

尝试一下
----

语法
--
```

encodeURIComponent(str);
```

### 参数

`uriComponent`

一个 string、number、boolean、null，undefined 或者任何 object。在编码之前，uriComponent 参数会被转化为字符串。

### 返回值

原字串作为 URI 组成部分被被编码后的新字符串。

描述
--

`encodeURIComponent` 转义除了如下所示外的所有字符：
```

不转义的字符：
    A-Z a-z 0-9 - _ . ! ~ * ' ( )
```

`encodeURIComponent()` 和 **`encodeURI`** 有以下几个不同点：

```js
var set1 = ";,/?:@&=+$"; // 保留字符
var set2 = "-\_.!~\*'()"; // 不转义字符
var set3 = "#"; // 数字标志
var set4 = "ABC abc 123"; // 字母数字字符和空格

console.log(encodeURI(set1)); // ;,/?:@&=+$
console.log(encodeURI(set2)); // -\_.!~\*'()
console.log(encodeURI(set3)); // #
console.log(encodeURI(set4)); // ABC%20abc%20123 (空格被编码为 %20)

console.log(encodeURIComponent(set1)); // %3B%2C%2F%3F%3A%40%26%3D%2B%24
console.log(encodeURIComponent(set2)); // -\_.!~\*'()
console.log(encodeURIComponent(set3)); // %23
console.log(encodeURIComponent(set4)); // ABC%20abc%20123 (空格被编码为 %20)
```

注意，如果试图编码一个非高 - 低位完整的代理字符，将会抛出一个 `URIError` 错误，例如：

```js
// 高低位完整
alert(encodeURIComponent("\uD800\uDFFF"));

// 只有高位，将抛出"URIError: malformed URI sequence"
alert(encodeURIComponent("\uD800"));

// 只有低位，将抛出"URIError: malformed URI sequence"
alert(encodeURIComponent("\uDFFF"));
```

为了避免服务器收到不可预知的请求，对任何用户输入的作为 URI 部分的内容你都需要用 encodeURIComponent 进行转义。比如，一个用户可能会输入"`Thyme &time=again`"作为`comment`变量的一部分。如果不使用 encodeURIComponent 对此内容进行转义，服务器得到的将是`comment=Thyme%20&time=again`。请注意，"&"符号和"="符号产生了一个新的键值对，所以服务器得到两个键值对（一个键值对是`comment=Thyme`，另一个则是`time=again`），而不是一个键值对。

对于 `application/x-www-form-urlencoded` (POST) 这种数据方式，空格需要被替换成 '+'，所以通常使用 `encodeURIComponent` 的时候还会把 "%20" 替换为 "+"。

为了更严格的遵循 RFC 3986（它保留 !, ', (, ), 和 \*），即使这些字符并没有正式划定 URI 的用途，下面这种方式是比较安全的：

```js
function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()\*]/g, function (c) {
    return "%" + c.charCodeAt(0).toString(16).toUpperCase();
  });
}
```

示例
--

下面这个例子提供了 UTF-8 下 `Content-Disposition` 和 `Link` 的服务器响应头信息的参数（例如 UTF-8 文件名)：

```js
var fileName = "my file(2).txt";
var header =
  "Content-Disposition: attachment; filename\*=UTF-8''" +
  encodeRFC5987ValueChars(fileName);

console.log(header);
// 输出 "Content-Disposition: attachment; filename\*=UTF-8''my%20file%282%29.txt"

function encodeRFC5987ValueChars(str) {
  return (
    encodeURIComponent(str)
      // 注意，尽管 RFC3986 保留 "!"，但 RFC5987 并没有
      // 所以我们并不需要过滤它。
      .replace(/['()]/g, escape) // i.e., %27 %28 %29
      .replace(/\\*/g, "%2A")
      // 下面的并不是 RFC5987 中 URI 编码必须的
      // 所以对于 |`^ 这 3 个字符我们可以稍稍提高一点可读性
      .replace(/%(?:7C|60|5E)/g, unescape)
  );
}

// 以下是上述功能的替换方案
function encodeRFC5987ValueChars2(str) {
  return (
    encodeURIComponent(str)
      // 注意，尽管 RFC3986 保留 "!"，但 RFC5987 并没有，
      // 所以我们并不需要过滤它。
      .replace(/['()\*]/g, (c) => "%" + c.charCodeAt(0).toString(16)) // i.e., %27 %28 %29 %2a (请注意，"\*" 的有效编码是 %2A
      // 这需要调用 toUpperCase() 方法来正确编码)
      // 以下并不是 RFC5987 编码所必须的，
      // 这样我们可以让 |`^ 在网络上获取更好的可读性
      .replace(/%(7C|60|5E)/g, (str, hex) =>
        String.fromCharCode(parseInt(hex, 16)),
      )
  );
}
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-encodeuricomponent-uricomponent |

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

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

参见
--

* `decodeURI`
* `encodeURI`
* `decodeURIComponent`


Float64Array - JavaScript

Float64Array
============

**`Float64Array`** 类型数组代表的是平台字节顺序为 64 位的浮点数型数组 (对应于 C 浮点数据类型) 。如果需要控制字节顺序，使用 `DataView` 替代。其内容初始化为`0`。一旦建立起来，你可以使用这个对象的方法对其元素进行操作，或者使用标准数组索引语法 (使用方括号)。

?语法
---
```

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

更多的语法信息和参数，参见 *TypedArray*.

属性
--

`Float64Array.BYTES_PER_ELEMENT`

返回元素字节数。在 `Float64Array` 的情况下返回 8。

Float64Array.length

长度属性的值为 3。关于其实际长度 (元素数量) 参见 `Float64Array.prototype.length`。

`Float64Array.prototype` (en-US)

*TypedArray*对象的原型。

方法
--

`Float64Array.from()`

从一个类数组对象或可遍历对象创建一个新的 Float64Array。参见 `Array.from()`。

`Float64Array.of()`

用可变数量的参数创建一个新的 Float64Array。参见 `Array.of()`。

`Float64Array` 属性
-----------------

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

### 特性

`Float64Array.prototype.constructor`

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

`Float64Array.prototype.buffer` 只读

返回这个`Float64Array 引用的` `ArrayBuffer`。构造时已固定，所以是**只读**的。

`Float64Array.prototype.byteLength` 只读

返回从`Float64Array 的``ArrayBuffer`开头开始`的`长度 (以字节为单位) 。构造时已固定，所以是**只读**的。

`Float64Array.prototype.byteOffset` 只读

返回从`Float64Array 的``ArrayBuffer`开头开始`的偏移量` (以字节为单位) 。构造时已固定，所以是**只读**的。

`Float64Array.prototype.length` 只读

返回 `Float64Array` 中的元素个数。构造时已固定，所以是**只读**的。

### 方法

`Float64Array.prototype.copyWithin()`

从数组复制元素。参见`Array.prototype.copyWithin()`。

`Float64Array.prototype.entries()`

`返回一个包含数组中每个元素键值对的数组遍历器对象`。参见`Array.prototype.entries()`。

`Float64Array.prototype.every()`

检测是否所有元素都能通过给定函数的测试。参见`Array.prototype.every()`。

`Float64Array.prototype.fill()`

用一个静态值填充给定的起始位置。参见`Array.prototype.fill()`。

`Float64Array.prototype.filter()`

创建一个新数组，数据为原数组中所有能让给入函数返回 true 的元素。参见`Array.prototype.filter()`。

`Float64Array.prototype.find()`

返回满足测试函数的值，如果没有找到，返回 undefined。参见`Array.prototype.find()`。

`Float64Array.prototype.findIndex()`

返回满足测试函数的值的位置，如果没有找到，返回 -1。参见`Array.prototype.findIndex()`。

`Float64Array.prototype.forEach()`

以每个元素为参数各调用一次函数。参见`Array.prototype.forEach()`。

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

判断是否包含某个元素，返回 `true` 或 `false`。参见`Array.prototype.includes()`。

`Float64Array.prototype.indexOf()`

返回数组中等于给定值的元素的第一个（最小）位置，没有找到则返回 -1。参见`Array.prototype.indexOf()`。

`Float64Array.prototype.join()`

合并所有数组元素到一个字符串中。参见`Array.prototype.join()`。

`Float64Array.prototype.keys()`

返回一个包含数组中所有索引的数组遍历器。参见`Array.prototype.keys()`。

`Float64Array.prototype.lastIndexOf()`

返回数组中等于给定值的元素的最后（最大）位置，没有找到则返回 -1。参见`Array.prototype.lastIndexOf()`。

`Float64Array.prototype.map()`

创建一个新的数组，数据由原数组每个元素依次传入给定函数后返回的值组成。参见`Array.prototype.map()`。

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

`Float64Array.prototype.copyWithin()`以前的一个非标准版本。

`Float64Array.prototype.reduce()`

传入一个函数作为累加器，从左到右遍历，最终得到一个值。参见`Array.prototype.reduce()`。

`Float64Array.prototype.reduceRight()`

传入一个函数作为累加器，从右到左遍历，最终得到一个值。参见`Array.prototype.reduceRight()`。

`Float64Array.prototype.reverse()`

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

`Float64Array.prototype.set()`

从给定的数组存入多个数值。

`Float64Array.prototype.slice()`

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

`Float64Array.prototype.some()`

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

`Float64Array.prototype.sort()`

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

`Float64Array.prototype.subarray()`

从给定的起始位置返回一个新的`Float64Array` 。

`Float64Array.prototype.values()`

返回一个包含所有数组元素的数组遍历器对象。参见`Array.prototype.values()`。

`Float64Array.prototype.toLocaleString()`

返回一个代表数组和其元素的本地化格式字符串。参见`Array.prototype.toLocaleString()`。

`Float64Array.prototype.toString()`

返回一个代表数组和它的元素的字符串。参见`Array.prototype.toString()`。

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

返回一个新的包含数组元素的数组迭代器对象。

示例
--

```js
// From a length
var float64 = new Float64Array(2);
float64[0] = 42;
console.log(float64[0]); // 42
console.log(float64.length); // 2
console.log(float64.BYTES\_PER\_ELEMENT); // 8

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

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

// From an ArrayBuffer
var buffer = new ArrayBuffer(32);
var z = new Float64Array(buffer, 0, 4);
```

规范
--

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

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

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

一致性提示
-----

从 ECMAScript 2015 (ES6) 开始，`Float32Array` 构造函数需要用一个 `new` 操作符来构造。现在直接把 `Float32Array` 构造函数当函数调用而不使用 new，会抛出一个 `TypeError`。

```js
var dv = Float64Array([1, 2, 3]);
// TypeError: calling a builtin Float64Array constructor
// 不允许不使用 new
```

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

参见
--

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


Int16Array - JavaScript

Int16Array
==========

**`Int16Array`** 类型化数组表示按平台字节顺序排列的 16 位有符号整数数组。如果需要控制字节顺序，请使用 `DataView` 代替。数组内容初始化为 `0`。建立后，可以使用对象的方法或标准数组索引语法（即使用方括号表示法）引用数组中的元素。

`Int16Array` 是隐藏类 `TypedArray` 的子类。

构造函数
----

`Int16Array()` (en-US)

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

静态属性
----

*从父对象 `TypedArray` 继承静态属性。*

`Int16Array.BYTES_PER_ELEMENT`

返回元素大小的数值。在 `Int16Array` 中该值为 `2`。

静态方法
----

*从父对象 `TypedArray` 继承静态方法。*

实例属性
----

*从父对象 `TypedArray` 继承实例属性。*

这些属性在 `Int16Array.prototype` 中定义，并为所有 `Int16Array` 实例共享。

`Int16Array.prototype.BYTES_PER_ELEMENT`

返回元素大小的数值。在 `Int16Array` 中该值为 `2`。

`Int16Array.prototype.constructor`

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

实例方法
----

*从父对象 `TypedArray` 继承实例方法。*

示例
--

### 创建 Int16Array 的不同方法

```js
// 给定长度
const int16 = new Int16Array(2);
int16[0] = 42;
console.log(int16[0]); // 42
console.log(int16.length); // 2
console.log(int16.BYTES\_PER\_ELEMENT); // 2

// 从一个数组
const x = new Int16Array([21, 31]);
console.log(x[1]); // 31

// 从另外一个 TypedArray
const y = new Int16Array(x);
console.log(y[0]); // 21

// 从一个 ArrayBuffer
const buffer = new ArrayBuffer(16);
const z = new Int16Array(buffer, 2, 4);
console.log(z.byteOffset); // 2

// 从可迭代对象
const iterable = (function\* () {
  yield\* [1, 2, 3];
})();
const int16FromIterable = new Int16Array(iterable);
console.log(int16FromIterable);
// Int16Array [1, 2, 3]
```

规范
--

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

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

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

参见
--

* `core-js` 中 `Int16Array` 的 polyfill
* JavaScript 类型化数组指南
* `TypedArray`
* `ArrayBuffer`
* `DataView`


BigInt - JavaScript

BigInt
======

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

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

* Learn more
* See full compatibility
* Report feedback
**`BigInt`** 是一种内置对象，它提供了一种方法来表示大于 `2^53 - 1` 的整数。这原本是 Javascript 中可以用 `Number` 表示的最大数字。**`BigInt`** 可以表示任意大的整数。

描述
--

可以用在一个整数字面量后面加 `n` 的方式定义一个 `BigInt` ，如：`10n`，或者调用函数 `BigInt()`（但不包含 `new` 运算符）并传递一个整数值或字符串值。

```js
const theBiggestInt = 9007199254740991n;

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

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

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

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

它在某些方面类似于 `Number` ，但是也有几个关键的不同点：不能用于 `Math` 对象中的方法；不能和任何 `Number` 实例混合运算，两者必须转换成同一种类型。在两种类型来回转换时要小心，因为 `BigInt` 变量在转换成 `Number` 变量时可能会丢失精度。

### 类型信息

使用 `typeof` 测试时， `BigInt` 对象返回 "bigint" ：

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

使用 `Object` 包装后， `BigInt` 被认为是一个普通 "object" ：

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

### 运算

以下操作符可以和 `BigInt` 一起使用： `+`、`*`、`-`、`**`、`%`。除 `>>>` （无符号右移）之外的 位操作 (en-US) 也可以支持。因为 `BigInt` 都是有符号的， `>>>` （无符号右移）不能用于 `BigInt`。为了兼容 asm.js，`BigInt` 不支持单目 (`+`) 运算符。

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

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

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

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

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

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

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

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

`/` 操作符对于整数的运算也没问题。可是因为这些变量是 `BigInt` 而不是 `BigDecimal` ，该操作符结果会向零取整，也就是说不会返回小数部分。

**警告：** 当使用 `BigInt` 时，带小数的运算会被取整。

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

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

### 比较

`BigInt` 和 `Number` 不是严格相等的，但是宽松相等的。

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

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

`Number` 和 `BigInt` 可以进行比较。

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

2n > 1;
// ↪ true

2 > 2;
// ↪ false

2n > 2;
// ↪ false

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

两者也可以混在一个数组内并排序。

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

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

注意被 `Object` 包装的 `BigInt` 使用 object 的比较规则进行比较，只用同一个对象在比较时才会相等。

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

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

### 条件

`BigInt` 在需要转换成 `Boolean` 的时表现跟 `Number` 类似：如通过 `Boolean` 函数转换；用于 `Logical Operators` (en-US) `||`, `&&`, 和 `!` 的操作数；或者用于在像 `if statement` 这样的条件语句中。

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

// ↪ "Hello from the else!"

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

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

Boolean(0n);
// ↪ false

Boolean(12n);
// ↪ true

!12n;
// ↪ false

!0n;
// ↪ true
```

构造器
---

`BigInt()`

创建`BigInt` 对象。

静态方法
----

`BigInt.asIntN()`

将 BigInt 值转换为一个 -2^(width-1) 与 2^(width-1) - 1 之间的有符号整数。

`BigInt.asUintN()`

将一个 BigInt 值转换为 0 与 2^(width) - 1 之间的无符号整数。

实例方法
----

`BigInt.prototype.toLocaleString()`

返回此数字的 language-sensitive 形式的字符串。覆盖 `Object.prototype.toLocaleString()` 方法。

`BigInt.prototype.toString()`

返回以指定基数 (base) 表示指定数字的字符串。覆盖 `Object.prototype.toString()` 方法。

`BigInt.prototype.valueOf()`

返回指定对象的基元值。覆盖 `Object.prototype.valueOf()` 方法。

使用建议
----

### 转化

由于在 `Number` 与 `BigInt` 之间进行转换会损失精度，因而建议仅在值可能大于 2^53 时使用 `BigInt` 类型，并且不在两种类型之间进行相互转换。

### 密码学

由于对 `BigInt` 的操作不是常数时间的，因而 `BigInt` 不适合用于密码学。

### 在 JSON 中使用

对任何 `BigInt` 值使用 `JSON.stringify()` 都会引发 `TypeError`，因为默认情况下 `BigInt` 值不会在 `JSON` 中序列化。但是，如果需要，可以实现 `toJSON` 方法：

```js
BigInt.prototype.toJSON = function () {
  return this.toString();
};
```

`JSON.stringify` 现在生成如下字符串，而不是抛出异常：

```js
JSON.stringify(BigInt(1));
// '"1"'
```

示例
--

### Calculating Primes

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

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

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

  return prime;
}

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

规范
--

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

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

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

参见
--

* `Number`


unescape() - JavaScript

unescape()
==========

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

**备注：** `unescape()` 是由浏览器实现的非标准函数，其仅针对跨引擎兼容性而进行了标准化。并不要求所有的 JavaScript 引擎都实现它，并且可能无法在所有地方都正常工作。如果可能的话，请使用 `decodeURIComponent()` 或 `decodeURI()`。

**`unescape()`** 函数计算一个新的字符串，将其中的十六进制转义序列替换为它们所代表的字符。转义序列可能是由 `escape()` 等函数引入的。

语法
--

```js
unescape(str)
```

### 参数

`str`

要解码的字符串。

### 返回值

一个其中的某些字符已被解码的新的字符串。

描述
--

`unescape` 函数是全局对象的函数属性。

`unescape()` 函数将任何转移序列替换为它所代表的字符。具体来说，它将任何形式为 `%XX` 或 `%uXXXX`（其中 `X` 代表一个十六进制数字）的转义序列替换为十六进制值为 `XX`/`XXXX` 的字符。如果转义序列无效（例如，如果 `%` 后面跟着一个或未跟十六进制数字），则保持不变。

**备注：** 该函数主要用于 URL 编码，其部分基于 RFC 1738 中的转义格式。`unescape()` 函数*不会*对字符串字面量中的转义序列进行求值。你可以将 `\xXX` 替换为 `%XX`，将 `\uXXXX` 替换为 `%uXXXX`，以获得一个可以被 `unescape()` 处理的字符串。

示例
--

### 使用 unescape()

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

规范
--

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

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

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

参见
--

* `core-js` 中 `unescape` 的 polyfill
* `decodeURI`
* `decodeURIComponent`
* `escape`


isFinite() - JavaScript

isFinite()
==========

该全局 **`isFinite()`** 函数用来判断被传入的参数值是否为一个有限数值（finite number）。在必要情况下，参数会首先转为一个数值。

尝试一下
----

语法
--

```js
isFinite(testValue)
```

### 参数

`testValue`

用于检测有限性（finiteness）的值。

### 描述

isFinite 是全局的方法，不与任何对象有关系。

你可以用这个方法来判定一个数字是否是有限数字。`isFinite` 方法检测它参数的数值。如果参数是 `NaN`，正无穷大或者负无穷大，会返回`false`，其他返回 `true`。

示例
--

```js
isFinite(Infinity); // false
isFinite(NaN); // false
isFinite(-Infinity); // false

isFinite(0); // true
isFinite(2e64); // true，在更强壮的 Number.isFinite(null) 中将会得到 false

isFinite("0"); // true，在更强壮的 Number.isFinite('0') 中将会得到 false
```

规范
--

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

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

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

参见
--

* `Number.isFinite()`
* `Number.NaN()`
* `Number.POSITIVE_INFINITY`
* `Number.NEGATIVE_INFINITY`


SharedArrayBuffer - JavaScript

SharedArrayBuffer
=================

**`SharedArrayBuffer`** 对象用来表示一个通用的原始二进制数据缓冲区，类似于 `ArrayBuffer` 对象，但它可以用来在共享内存上创建视图。与可转移的 `ArrayBuffer` 不同，`SharedArrayBuffer` 不是可转移对象。

描述
--

要在集群中的一个代理（agent，可以是网页的主程序或其任意一个 web worker）与另一个代理之间使用 `ShareArrayBuffer` 共享内存，需要使用 `postMessage` 和结构化克隆。

结构化克隆算法接受 `SharedArrayBuffer` 对象和映射到 `SharedArrayBuffer` 对象的类型化数组。在这两种情况下， `SharedArrayBuffer` 对象会被传输给接收者，从而在接收代理中产生一个新的、私有的 `SharedArrayBuffer` 对象（就像 `ArrayBuffer` 一样）。但是，两个 `SharedArrayBuffer` 对象指向的共享数据块其实是同一个数据块，一个代理中对数据块的修改最终会将在另一个代理中可见。

```js
const sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);
```

共享内存可以被 worker 线程或主线程创建和同时更新。根据系统（CPU、操作系统、浏览器）的不同，需要一段时间才能将变化传递给所有上下文环境。因此需要通过原子操作来进行同步。

`SharedArrayBuffer` 被一些 web API 使用，比如：

* `WebGLRenderingContext.bufferData()`
* `WebGLRenderingContext.bufferSubData()` (en-US)
* `WebGL2RenderingContext.getBufferSubData()` (en-US)
### 安全需求

由于幽灵漏洞，共享内存和高精度定时器在 2018 年 1 月 5 日开始被禁用。在 2020 年，一种新的、安全的方法已经被标准化，以重新启用共享内存。

作为基本要求，你的文档需要处于一个安全上下文中。

对于顶级文档，需要设置两个标头来实现你网站的跨源隔离：

* `Cross-Origin-Opener-Policy` (en-US) 设置为 `same-origin`（来保护你的源站点免受攻击）
* `Cross-Origin-Embedder-Policy` 设置为 `require-corp` 或 `credentialless`（保护受害者免受你的源站点的影响）

```http
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

为了验证跨源隔离是否生效，你可以测试窗口和 worker 线程上下文中是否存在 `crossOriginIsolated` 属性：

```js
const myWorker = new Worker("worker.js");

if (crossOriginIsolated) {
  const buffer = new SharedArrayBuffer(16);
  myWorker.postMessage(buffer);
} else {
  const buffer = new ArrayBuffer(16);
  myWorker.postMessage(buffer);
}
```

在设置了这两个标头后，`postMessage()` 不再为 `SharedArrayBuffer` 对象抛出错误，因此，跨线程共享内存现在可用。

嵌套文档和专用 worker 线程也需要将 `Cross-Origin-Embedder-Policy` 标头设置为同样的值。对于同源嵌套文档和子资源，不需要进行任何其他更改。同站（但跨源）嵌套文档和子资源需要将 `Cross-Origin-Resource-Policy` 标头设置为 `same-site`。而它们的跨源（和跨站点）的对应部分也需要将同样的标头设置为 `cross-origin`。请注意，将 `Cross-Origin-Resource-Policy` 标头设置为除 `same-origin` 之外的任何值，都会使资源暴露于潜在的攻击中，比如幽灵漏洞。

请注意，`Cross-Origin-Opener-Policy` (en-US) 标头会限制你对弹出窗口引用的保留能力。两个顶级窗口上下文之间的直接访问基本上只在它们同源且携带相同的两个标头（且具有相同的值）时才可行。

### API 可用性

根据是否采取了上述安全措施，各类内存共享 API 具有不同的可用性：

* `Atomics` 对象总是可用的。
* `SharedArrayBuffer` 对象在原则上始终可用，但遗憾的是，除非设置了前面提到的两个标头，否则其在全局对象上的构造函数是隐藏的，这是为了兼容 web 内容。这个限制有望在未来被移除。尽管如此，仍然可以用 `WebAssembly.Memory` 来获取实例。
* 除非设置了上文提到的两个标头，否则各种 `postMessage()` 的 API 在处理 `SharedArrayBuffer` 对象时会抛出异常。如果正确设置了这两个标头，`Window` 对象和专用 worker 线程上的 `postMessage()` 都可以正常工作，并允许跨线程共享内存。
### WebAssembly 共享内存

`WebAssembly.Memory` 对象可以通过设置 `shared` (en-US) 构造函数标志来创建。当这个标志设置为 `true` 时，构造出的 `Memory` 对象就像 `SharedArrayBuffer` 一样，可以通过 `postMessage()` 在 worker 线程之间共享，而且 `Memory` 对象的后备 `buffer` (en-US) 是一个 `SharedArrayBuffer`。因此，上述关于在 worker 线程间共享 SharedArrayBuffer 的要求同样适用于共享 `WebAssembly.Memory`。

WebAssembly Thread 提案还定义了一套新的原子指令。就像 `SharedArrayBuffer` 及其方法始终可用（并且只有在设置了新标头的情况下，才允许线程间共享）一样，WebAssembly 原子指令也是始终可用的。

### 增大 SharedArrayBuffer

`SharedArrayBuffer` 对象可以通过在调用 `SharedArrayBuffer()` 时包含 `maxByteLength` 选项来使其可增大。你可以通过访问 `SharedArrayBuffer` 的 `growable` 和 `maxByteLength` 属性来分别查询其是否可增大以及其最大大小。你还可以通过调用 `grow()` 为一个可增大的 `SharedArrayBuffer` 分配新的大小。新字节被初始化为 0。

这些特性令增大 `SharedArrayBuffer` 更为高效——否则，你必须创建一个新大小的缓冲区副本。它还使得 JavaScript 在这方面与 WebAssembly 保持一致（Wasm 线性内存可以通过 `WebAssembly.Memory.prototype.grow()` (en-US) 调整大小）。

出于安全原因，`SharedArrayBuffer` 的大小无法缩小，只能增大。

构造函数
----

`SharedArrayBuffer()`

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

静态属性
----

`SharedArrayBuffer[@@species]`

返回用于构造 `SharedArrayBuffer` 方法返回值的构造函数。

实例属性
----

属性定义于 `SharedArrayBuffer.prototype` 并且被所有 `SharedArrayBuffer` 实例所共享。

`SharedArrayBuffer.prototype.byteLength`

数组大小，以字节为单位。在构造数组时被确定，并且只能在可增大的 `SharedArrayBuffer`上通过 `SharedArrayBuffer.prototype.grow()` 方法来改变。

`SharedArrayBuffer.prototype.constructor`

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

`SharedArrayBuffer.prototype.growable`

只读。如果当前 `SharedArrayBuffer` 可以增大，则返回 `true`，否则返回 `false`。

`SharedArrayBuffer.prototype.maxByteLength`

当前 `SharedArrayBuffer` 可以增大的最大长度，只读，以字节为单位。在构造数组时确定且无法更改。

`SharedArrayBuffer.prototype[@@toStringTag]`

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

实例方法
----

`SharedArrayBuffer.prototype.grow()`

增大当前 `SharedArrayBuffer` 到指定大小，以字节为单位。

`SharedArrayBuffer.prototype.slice()`

返回一个新的 `SharedArrayBuffer`，其内容是当前 `SharedArrayBuffer` 从 `begin`（含）到 `end`（不含）的字节的副本。如果 `begin` 或 `end` 为负，则它是从数组的末尾开始的索引，而不是数组的开头。

示例
--

### 创建一个新的 SharedArrayBuffer

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

### 截取 SharedArrayBuffer

```js
sab.slice(); // SharedArrayBuffer { byteLength: 1024 }
sab.slice(2); // SharedArrayBuffer { byteLength: 1022 }
sab.slice(-2); // SharedArrayBuffer { byteLength: 2 }
sab.slice(0, 1); // SharedArrayBuffer { byteLength: 1 }
```

### 在 WebGL buffer 中使用

```js
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY\_BUFFER, buffer);
gl.bufferData(gl.ARRAY\_BUFFER, sab, gl.STATIC\_DRAW);
```

规范
--

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

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

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

参见
--

* `Atomics`
* `ArrayBuffer`
* JavaScript 类型化数组指南
* Web Workers
* 共享内存——简明教程，TC39 ecmascript-sharedmem 提案
* JavaScript 新并发原语的初体验，hacks.mozilla.org（2016）
* COOP 和 COEP 的解释，由 Chrome 团队撰写（2020）
* `Cross-Origin-Opener-Policy` (en-US)
* `Cross-Origin-Embedder-Policy`
* `Cross-Origin-Resource-Policy`
* `crossOriginIsolated`
* Android Chrome 88 和桌面版 Chrome 92 中的 SharedArrayBuffer 更新，developer.chrome.com（2021）


BigInt64Array - JavaScript

BigInt64Array
=============

**`BigInt64Array`** 类型的数组代表由 64 位有符号整数组成的数组。如果需要控制字节顺序的话，请使用 `DataView` 代替。内容初始化为 `0n`。一旦建立，就可以使用对象的方法或使用标准数组索引语法（即使用中括号表示法）引用数组中的元素。

构造函数
----

`BigInt64Array()` (en-US)

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

静态属性
----

`BigInt64Array.BYTES_PER_ELEMENT`

返回一个元素大小的数字值。`BigInt64Array` 返回 `8` 。

静态方法
----

`BigInt64Array.from()`

从类数组或者可迭代对象创建一个新的 `BigInt64Array`，另请参见 `Array.from()`。

`BigInt64Array.of()`

从可变数量的参数创建一个新的 `BigInt64Array`，另请参见 `Array.of()`。

实例属性
----

`BigInt64Array.prototype.buffer`

返回被 `BigInt64Array` 引用的 `ArrayBuffer`。这在 `BigInt64Array` 对象构建时期就被锁定了，所以是**只读的**。

`BigInt64Array.prototype.byteLength`

返回 `BigInt64Array` 从 `ArrayBuffer` 开始的长度（以字节为单位）。这在 `BigInt64Array` 对象构建时期就被锁定了，所以是**只读的**。

`BigInt64Array.prototype.byteOffset`

返回 `BigInt64Array` 从 `ArrayBuffer` 开始的偏移量（以字节为单位）。这在 `BigInt64Array` 对象构建时期就被锁定了，所以是**只读的**。

`BigInt64Array.prototype.length`

返回 `BigInt64Array` 中被保留的元素个数。这在 `BigInt64Array` 对象构建时期就被锁定了，所以是**只读的**。

实例方法
----

`BigInt64Array.prototype.copyWithin()`

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

`BigInt64Array.prototype.entries()`

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

`BigInt64Array.prototype.every()`

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

`BigInt64Array.prototype.fill()`

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

`BigInt64Array.prototype.filter()`

使用提供的筛选函数为其返回 `true` 的数组的所有元素创建一个新数组。另请参见 `Array.prototype.filter()`。

`BigInt64Array.prototype.find()`

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

`BigInt64Array.prototype.findIndex()`

如果数组中的元素满足提供的测试函数，则返回数组中找到的索引；如果未找到，则返回 `-1`。另请参见 `Array.prototype.findIndex()`。

`BigInt64Array.prototype.forEach()`

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

`BigInt64Array.prototype.includes()`

确定类型化数组是否包含某个元素，并根据需要返回 `true` 或 `false` 。另请参见 `Array.prototype.includes()`。

`BigInt64Array.prototype.indexOf()`

返回数组中元素的第一个（最小）索引，等于指定值；如果找不到，则返回 `-1`。另请参见 `Array.prototype.indexOf()`。

`BigInt64Array.prototype.join()`

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

`BigInt64Array.prototype.keys()`

返回一个新的 *array iterator*，它包含数组中每个索引的键。另请参见 `Array.prototype.keys()`。

`BigInt64Array.prototype.lastIndexOf()`

返回数组中元素的最后一个（最大）索引，等于指定值；如果找不到，则返回 `-1`。另请参见 `Array.prototype.lastIndexOf()`。

`BigInt64Array.prototype.map()`

创建一个新数组，其中包含对此数组中的每个元素调用所提供函数的结果。另请参见 `Array.prototype.map()`。

`BigInt64Array.prototype.reduce()`

对累加器和数组的每个值（从左到右）应用一个函数，以便将其减少为单个值。另请参见 `Array.prototype.reduce()`。

`BigInt64Array.prototype.reduceRight()`

对累加器和数组的每个值（从右到左）应用一个函数，以便将其减少为单个值。另请参见 `Array.prototype.reduceRight()`。

`BigInt64Array.prototype.reverse()`

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

`BigInt64Array.prototype.set()`

在 `TypedArray` 中存储多个值，从指定数组读取输入值。

`BigInt64Array.prototype.slice()`

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

`BigInt64Array.prototype.some()`

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

`BigInt64Array.prototype.sort()`

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

`BigInt64Array.prototype.subarray()`

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

`BigInt64Array.prototype.values()`

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

`BigInt64Array.prototype.toLocaleString()`

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

`BigInt64Array.prototype.toString()`

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

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

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

示例
--

### 不同的方法去创建一个 `BigInt64Array`

```js
// From a length
var bigint64 = new BigInt64Array(2);
bigint64[0] = 42n;
console.log(bigint64[0]); // 42n
console.log(bigint64.length); // 2
console.log(bigint64.BYTES\_PER\_ELEMENT); // 8

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

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

// From an ArrayBuffer
var buffer = new ArrayBuffer(32);
var z = new BigInt64Array(buffer, 0, 4);

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

规范
--

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

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

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

参见
--

* JavaScript typed arrays
* `BigUint64Array` (en-US)
* `DataView`


AsyncGenerator.prototype.throw() - JavaScript

AsyncGenerator.prototype.throw()
================================

`AsyncGenerator` 实例的 **`throw()`** 方法的作用就好像一个 `throw` 语句被插入到生成器主体的当前暂停位置，这会通知生成器错误的情况并允许其处理错误，或者执行清理和自行关闭。

语法
--

```js
asyncGeneratorInstance.throw(exception)
```

### 参数

`exception`

要抛出的异常。使用 `Error` 实例对调试非常有帮助。

### 返回值

如果抛出的错误没有被捕获，它会返回一个以传入的异常拒绝的 `Promise`。

如果抛出的异常被 `try...catch` 捕获并且生成器恢复生成更多的值，它将返回一个 `Promise`，其兑现为带有两个属性的 `Object`：

`done`

一个布尔值：

* 如果该生成器函数的控制流程已经结束，则为 `true`。
* 如果该生成器函数还能产生更多的值，则为 `false`。

`value`

下一个 `yeild` 表达式生成的值。

示例
--

### 使用 throw()

以下示例展示了一个简单生成器和使用 `throw` 方法抛出的错误。像往常一样，错误可以通过 `try...catch` 块捕获。

```js
// 异步任务。假设它在实践中做了一些更有用的事情。
function sleep(time) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, time);
  });
}

async function\* createAsyncGenerator() {
  while (true) {
    try {
      await sleep(500);
      yield 42;
    } catch (e) {
      console.error(e);
    }
  }
}

const asyncGen = createAsyncGenerator();
asyncGen.next(1).then((res) => console.log(res)); // { value: 42, done: false }
asyncGen
  .throw(new Error("出了点问题")) // Error: 出了点问题
  .then((res) => console.log(res)); // { value: 42, done: false }
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-asyncgenerator-prototype-throw |

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

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

参见
--

* `async function*`
* 迭代器和生成器指南


AsyncGenerator.prototype.next() - JavaScript

AsyncGenerator.prototype.next()
===============================

`AsyncGenerator` 实例的 **`next()`** 方法返回序列中的下一个值。

语法
--

```js
next()
next(value)
```

### 参数

`value` 可选

用于修改生成器内部状态的可选值。传入给 `next()` 方法的值将被 `yield` 接收。

### 返回值

一个 `Promise`，其兑现时将返回一个 `Object`，包含以下两个属性：

`done`

一个布尔值：

* 如果生成器的控制流程已经结束，则为 `true`。在这种情况下，`value` 指定生成器的*返回值*（可能是 undefined）。
* 如果生成器还能产生更多的值，则为 `false`。

`value`

生成器产生或返回的任何 JavaScript 值。

示例
--

### 使用 next()

以下示例展示了一个简单的生成器以及调用 `next` 方法后返回的对象：

```js
// 异步任务。假设它在实践中做了一些更有用的事情。
function delayedValue(time, value) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(value), time);
  });
}

async function\* createAsyncGenerator() {
  yield delayedValue(500, 1);
  yield delayedValue(500, 2);
  yield delayedValue(500, 3);
}

const asyncGen = createAsyncGenerator();
asyncGen.next().then((res) => console.log(res)); // { value: 1, done: false }
asyncGen.next().then((res) => console.log(res)); // { value: 2, done: false }
asyncGen.next().then((res) => console.log(res)); // { value: 3, done: false }
asyncGen.next().then((res) => console.log(res)); // { value: undefined, done: true }
```

### 向生成器传值

在此示例中，调用 `next` 时传入了值。

**备注：** 第一次调用不会打印任何内容，因为生成器最初没有产生任何内容。

```js
// 异步任务。假设它在实践中做了一些更有用的事情。
function sleep(time) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, time);
  });
}

async function\* createAsyncGenerator() {
  while (true) {
    await sleep(500);
    const value = yield;
    console.log(value);
  }
}

async function main() {
  const asyncGen = createAsyncGenerator();
  // 这一步不会有输出：通过 `next` 发送的第一个值会被丢弃
  console.log(await asyncGen.next(1)); // { value: undefined, done: false }
  // 打印通过 `next` 发送的值——2
  console.log(await asyncGen.next(2)); // { value: undefined, done: false }
}

main();
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-asyncgenerator-prototype-next |

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

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

参见
--

* `async function*`
* 迭代器和生成器指南


AsyncGenerator.prototype.return() - JavaScript

AsyncGenerator.prototype.return()
=================================

`AsyncGenerator` 实例的 **`return()`** 方法的作用就好像一个 `return` 语句被插入到生成器主体的当前暂停位置，这会结束生成器并允许生成器与 `try...finally` 块结合使用时执行任何清理任务。

语法
--

```js
asyncGeneratorInstance.return()
asyncGeneratorInstance.return(value)
```

### 参数

`value` 可选

要返回的值。

### 返回值

一个 `Promise`，其兑现为一个 `Object`，包含以下两个属性：

`done`

一个布尔值：

* 如果生成器函数的控制流程已经结束，则为 `true`。
* 如果生成器函数的控制流程还未结束并且还能产生更多的值，则为 `false`。只有在 `try...finally` 中捕获 `return` 并且 `finally` 块中还有更多的 `yield` 表达式时才会发生这种情况。

`value`

给定的作为参数的值，或者，如果 `yield` 表达式包含在 `try...finally`，从 `finally` 块产生/返回的值。

描述
--

`return()` 方法在被调用时，可以看作是在生成器主体当前暂停的位置插入了一个 `return value;` 语句，其中 `value` 是传入给 `return()` 方法的值。因此，在典型的流程中，调用 `return(value)` 将返回 `{done: true, value: value }`。然而，如果 `yield` 表达式被包含在 `try...finally` 块中，控制流不会退出函数体，而是进入 `finally` 块。在这种情况下，如果 `finally` 块中有更多 `yield` 表达式，返回的值可能会不同，`done` 甚至可能是 `false`。

示例
--

### 使用 return()

以下例子展示了一个简单的异步生成器和 `return` 方法的使用。

```js
// 异步任务。假设它在实践中做了一些更有用的事情。
function delayedValue(time, value) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(value), time);
  });
}

async function\* createAsyncGenerator() {
  yield delayedValue(500, 1);
  yield delayedValue(500, 2);
  yield delayedValue(500, 3);
}

const asyncGen = createAsyncGenerator();
asyncGen.next().then((res) => console.log(res)); // { value: 1, done: false }
asyncGen.return("foo").then((res) => console.log(res)); // { value: "foo", done: true }
asyncGen.next().then((res) => console.log(res)); // { value: undefined, done: true }
```

### 生成器结束后使用 return()

如果没有给 `return()` 方法传入 `value` 参数，promise 将会像 next() 方法被调用了一样兑现。在本示例中，生成器已经结束，因此返回的值是 `undefined`。

在生成器处于“完成”状态后，仍然可以调用 `return()`，但是生成器将保持此状态。

```js
async function\* createAsyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
  yield await Promise.resolve(3);
}
const asyncGen = createAsyncGenerator();
asyncGen.next().then((res) => console.log(res)); // { value: 1, done: false }
asyncGen.next().then((res) => console.log(res)); // { value: 2, done: false }
asyncGen.next().then((res) => console.log(res)); // { value: 3, done: false }
// 返回的值是 undefined，因为没有传入任何值并且生成器已经 'done'
asyncGen.return().then((res) => console.log(res)); // { value: undefined, done: true }
// 即使生成器完成，我们仍然可以返回一个值
asyncGen.return(1).then((res) => console.log(res)); // { value: 1, done: true }
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-asyncgenerator-prototype-return |

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

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

参见
--

* `async function*`
* 迭代器和生成器指南


AggregateError() 构造函数 - JavaScript

AggregateError() 构造函数
=====================

**`AggregateError()`** 构造函数创建了一个包装了多个错误对象的单个错误对象。

语法
--

```js
new AggregateError(errors)
new AggregateError(errors, message)
new AggregateError(errors, message, options)

AggregateError(errors)
AggregateError(errors, message)
AggregateError(errors, message, options)
```

**备注：** 调用 `AggregateError()` 可以使用或不使用 `new`，两种方法都会创建一个新的 `AggregateError` 实例。

### 参数

`errors`

一系列错误对象，实际上可能不是 `Error` 的实例。

`message` 可选

一个可选的对错误集合的可读描述。

`options` 可选

一个具有以下属性的对象：

`cause` 可选

表示错误的具体原因的属性。当捕捉并重新抛出一个带有更具体或有用的错误信息的错误时，这个属性可以用来传递原始错误。

示例
--

### 创建 AggregateError

```js
try {
  throw new AggregateError([new Error("some error")], "Hello");
} catch (e) {
  console.log(e instanceof AggregateError); // true
  console.log(e.message); // "Hello"
  console.log(e.name); // "AggregateError"
  console.log(e.errors); // [ Error: "some error" ]
}
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-aggregate-error-constructor |

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

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

参见
--

* `core-js` 中 `AggregateError` 的 polyfill
* `Promise.any`


ArrayBuffer.prototype.transferToFixedLength() - JavaScript

ArrayBuffer.prototype.transferToFixedLength()
=============================================

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

`ArrayBuffer` 实例的 **`transferToFixedLength()`** 方法创建一个不可调整大小的新 `ArrayBuffer` 对象，该对象与此缓冲区具有相同的字节内容，然后将此缓冲区分离。

语法
--

```js
transferToFixedLength()
transferToFixedLength(newByteLength)
```

### 参数

`newByteLength`

新的 `ArrayBuffer` 的 `byteLength`。默认为此 `ArrayBuffer` 的 `byteLength`。

* 如果 `newByteLength` 小于此 `ArrayBuffer` 的 `byteLength`，则“溢出的”字节将被丢弃。
* 如果 `newByteLength` 大于此 `ArrayBuffer` 的 `maxByteLength`，则多余的字节用零填充。

### 返回值

一个新的 `ArrayBuffer` 对象。它的内容被初始化为此 `ArrayBuffer` 的内容，如果有多余的字节，则用零填充。新的 `ArrayBuffer` 总是不可调整大小的。原始 `ArrayBuffer` 被分离。

### 异常

`TypeError`

如果此 `ArrayBuffer` 已经分离，则抛出该错误。

描述
--

和 `transfer()` 不同，`transferToFixedLength()` 总是创建一个不可调整大小的 `ArrayBuffer`。这意味着 `newByteLength` 可以比 `maxByteLength` 大，即使此 `ArrayBuffer` 是可调整大小的。有关更多信息，请参阅传输 ArrayBuffer。

示例
--

### 将可调整大小的 ArrayBuffer 转换为固定长度

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const view = new Uint8Array(buffer);
view[1] = 2;
view[7] = 4;

const buffer2 = buffer.transferToFixedLength();
console.log(buffer2.byteLength); // 8
console.log(buffer2.resizable); // false
const view2 = new Uint8Array(buffer2);
console.log(view2[1]); // 2
console.log(view2[7]); // 4
```

通过使用 `transferToFixedLength`，`newByteLength` 可以大于原来的 `ArrayBuffer` 的 `maxByteLength`。

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const view = new Uint8Array(buffer);
view[1] = 2;
view[7] = 4;

const buffer2 = buffer.transferToFixedLength(20);
console.log(buffer2.byteLength); // 20
console.log(buffer2.resizable); // false
const view2 = new Uint8Array(buffer2);
console.log(view2[1]); // 2
console.log(view2[7]); // 4
```

规范
--

| Specification |
| --- |
| ArrayBuffer transfer # sec-arraybuffer.prototype.transfertofixedlength |

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

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

参见
--

* `ArrayBuffer`
* `ArrayBuffer.prototype.detached`
* `ArrayBuffer.prototype.transfer()`


ArrayBuffer.prototype.slice() - JavaScript

ArrayBuffer.prototype.slice()
=============================

`ArrayBuffer` 实例的 **`slice()`** 方法返回一个新的 `ArrayBuffer` 实例，其包含原 `ArrayBuffer` 实例中从 `begin` 开始（包含）到 `end` 结束（不含）的所有字节的副本。

尝试一下
----

语法
--

```js
slice()
slice(start)
slice(start, end)
```

### 参数

`start` 可选

要开始提取的位置索引（从 0 开始），将被转换为整数。

* 负数索引将会从缓冲区末尾开始计算——如果 `start < 0`，那么将会使用 `start + buffer.length`。
* 如果 `start < -buffer.length` 或省略了 `start`，则会使用 `0`。
* 如果 `start >= buffer.length`，则不会提取任何内容。

`end` 可选

要结束提取的位置索引（从 0 开始），将被转换为整数。`slice()` 提取到但不包括 `end`。

* 负数索引将会从缓冲区末尾开始计算——如果 `end < 0`，那么将会使用 `end + buffer.length`。
* 如果 `end < -buffer.length`，则会使用 `0`。
* 如果 `end >= buffer.length` 或省略了 `end`，则会使用 `buffer.length`，则会导致直到末尾的所有元素都被提取。
* 如果标准化后的 `end` 位置在 `start` 位置之前，则不会提取任何内容。

### 返回值

一个新的 `ArrayBuffer` 对象。

示例
--

### 复制一个 ArrayBuffer

```js
const buf1 = new ArrayBuffer(8);
const buf2 = buf1.slice(0);
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-arraybuffer.prototype.slice |

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

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

参见
--

* `ArrayBuffer`


ArrayBuffer.prototype.resize() - JavaScript

ArrayBuffer.prototype.resize()
==============================

`ArrayBuffer` 实例的 **`resize()`** 方法将 `ArrayBuffer` 调整为指定的大小，以字节为单位。

尝试一下
----

语法
--

```js
resize(newLength)
```

### 参数

`newLength`

`ArrayBuffer` 要调整到的新的长度，以字节为单位。

### 返回值

无（`undefined`）。

### 异常

`TypeError`

如果 `ArrayBuffer` 已分离或不可调整大小，则抛出该错误。

`RangeError`

如果 `newLength` 大于该 `ArrayBuffer` 的 `maxByteLength`，则抛出该错误。

描述
--

`resize()` 方法将 `ArrayBuffer` 调整为 `newLength` 参数指定的大小，前提是该 `ArrayBuffer` 是可调整大小的并且新的大小小于或等于该 `ArrayBuffer` 的 `maxByteLength`。新字节被初始化为 0。

请注意，你可以使用 `resize()` 来缩小和增大 `ArrayBuffer`——即使 `newLength` 小于 `ArrayBuffer` 的当前 `byteLength`。

示例
--

### 使用 resize()

在这个示例中，我们创建一个 8 字节缓冲区，该缓冲区可调整大小到的最大长度是 16 字节，然后检查其 `resizable` 属性，如果 `resizable` 返回 `true` 则调整其大小：

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

if (buffer.resizable) {
  console.log("缓冲区大小是可调整的！");
  buffer.resize(12);
}
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-arraybuffer.prototype.resize |

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

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

参见
--

* `ArrayBuffer`
* `ArrayBuffer.prototype.resizable`
* `ArrayBuffer.prototype.maxByteLength`


ArrayBuffer.prototype.transfer() - JavaScript

ArrayBuffer.prototype.transfer()
================================

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

`ArrayBuffer` 实例的 **`transfer()`** 方法创建一个内容与该缓冲区相同的新 `ArrayBuffer` 实例，然后将当前缓冲区分离。

语法
--

```js
transfer()
transfer(newByteLength)
```

### 参数

`newByteLength` 可选

新的 `ArrayBuffer` 的 `byteLength`。默认为当前 `ArrayBuffer` 的 `byteLength`。

* 如果 `newByteLength` 小于当前 `ArrayBuffer` 的 `byteLength`，“溢出”的字节将被丢弃。
* 如果 `newByteLength` 大于当前 `ArrayBuffer` 的 `byteLength`，剩下的的字节将用零填充。
* 如果当前的 `ArrayBuffer` 是可调整大小的，`newByteLength` 一定不能大于其 `maxByteLength`。

### 返回值

一个新的 `ArrayBuffer` 对象。其内容被初始化为当前 `ArrayBuffer` 的内容，如果有额外的字节。则填充为零。当且仅当当前 `ArrayBuffer` 是可调整大小的，新 `ArrayBuffer` 才是可调整大小的，在这种情况下，其 `maxByteLength` 和当前 `ArrayBuffer` 的相同。当前 `ArrayBuffer` 将被分离。

### 异常

`RangeError`

如果当前 `ArrayBuffer` 是可调整大小的并且 `newByteLength` 大于当前 `ArrayBuffer` 的 `maxByteLength`，则抛出此错误。

`TypeError`

如果当前 `ArrayBuffer` 已经分离，则抛出此错误。

描述
--

`transfer()` 方法执行与结构化克隆算法相同的操作。它将当前 `ArrayBuffer` 的字节复制到一个新的 `ArrayBuffer` 对象中，然后分离当前 `ArrayBuffer` 对象。有关更多信息，请参阅传输 ArrayBuffer。

`transfer()` 保留了当前 `ArrayBuffer` 的大小可调整性。如果你希望新的 `ArrayBuffer` 不可调整大小，请使用 `transferToFixedLength()` 代替。没有办法通过传输使长度固定的缓冲区变为可调整大小的缓冲区。

`transfer()` 是非常高效的，因为（引擎）实现可能以零拷贝移动或 `realloc`——没有实际数据的复制——来实现此方法。

示例
--

### 传输一个 ArrayBuffer

```js
// 创建一个 ArrayBuffer 并写入一些字节
const buffer = new ArrayBuffer(8);
const view = new Uint8Array(buffer);
view[1] = 2;
view[7] = 4;

// 将缓冲区复制到另一个相同大小的缓冲区
const buffer2 = buffer.transfer();
console.log(buffer.detached); // true
console.log(buffer2.byteLength); // 8
const view2 = new Uint8Array(buffer2);
console.log(view2[1]); // 2
console.log(view2[7]); // 4

// 将缓冲区复制到一个更小的缓冲区
const buffer3 = buffer2.transfer(4);
console.log(buffer3.byteLength); // 4
const view3 = new Uint8Array(buffer3);
console.log(view3[1]); // 2
console.log(view3[7]); // undefined

// 将缓冲区复制到一个更大的缓冲区
const buffer4 = buffer3.transfer(8);
console.log(buffer4.byteLength); // 8
const view4 = new Uint8Array(buffer4);
console.log(view4[1]); // 2
console.log(view4[7]); // 0

// 已经分离，抛出 TypeError
buffer.transfer(); // TypeError: Cannot perform ArrayBuffer.prototype.transfer on a detached ArrayBuffer
```

### 传输一个可调整大小的 ArrayBuffer

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const view = new Uint8Array(buffer);
view[1] = 2;
view[7] = 4;

// 将缓冲区复制到一个更小的缓冲区
const buffer2 = buffer.transfer(4);
console.log(buffer2.byteLength); // 4
console.log(buffer2.maxByteLength); // 16
const view2 = new Uint8Array(buffer2);
console.log(view2[1]); // 2
console.log(view2[7]); // undefined
buffer2.resize(8);
console.log(view2[7]); // 0

// 将缓冲区复制到一个大小在 maxByteLength 內但更大的缓冲区
const buffer3 = buffer2.transfer(12);
console.log(buffer3.byteLength); // 12

// 将缓冲区复制到一个大小超过 maxByteLength 的更大的缓冲区
buffer3.transfer(20); // RangeError: Invalid array buffer length
```

规范
--

| Specification |
| --- |
| ArrayBuffer transfer # sec-arraybuffer.prototype.transfer |

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

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

参见
--

* `ArrayBuffer`
* `ArrayBuffer.prototype.detached`
* `ArrayBuffer.prototype.transferToFixedLength()`


ArrayBuffer() 构造函数 - JavaScript

ArrayBuffer() 构造函数
==================

**`ArrayBuffer()`** 构造函数创建 `ArrayBuffer` 对象。

尝试一下
----

语法
--

```js
new ArrayBuffer(length)
new ArrayBuffer(length, options)
```

**备注：** `ArrayBuffer()` 只能使用 `new` 构造。尝试在没有 `new` 的情况下调用会抛出 `TypeError`。

### 参数

`length`

要创建的数组缓冲区的大小（以字节为单位）。

`options` 可选

一个对象，可以包含以下属性：

`maxByteLength` 可选

数组缓冲区可以调整到的最大大小，以字节为单位。

### 返回值

一个指定大小的新 `ArrayBuffer` 对象，其 `maxByteLength` 属性设置为指定的 `maxByteLength`（如果指定了该值），其内容被初始化为 0。

### 异常

`RangeError`

有下列情况之一时抛出：

* `length` 或 `maxByteLength` 大于 `Number.MAX_SAFE_INTEGER`（≥ 253）或者为负数。
* `length` 大于 `maxByteLength`。

示例
--

### 创建一个 ArrayBuffer

在这个示例中，我们创建一个 8 字节的缓冲区，并使用一个 `Int32Array` 视图来引用该缓冲区：

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

### 创建一个可以调整大小的 ArrayBuffer

在这个示例中，我们创建一个 8 字节的缓冲区，它可以调整到的最大长度为 16 字节，然后使用 `resize()` 调整到 12 字节：

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

buffer.resize(12);
```

**备注：** 推荐将 `maxByteLength` 设置为使用场景下最小的大小。它不应超过 `1073741824`（1GB），以减少内存溢出风险。

规范
--

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

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

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

参见
--

* `core-js` 中 `ArrayBuffer` 的 polyfill
* JavaScript 类型化数组指南
* `SharedArrayBuffer`


ArrayBuffer.prototype.resizable - JavaScript

ArrayBuffer.prototype.resizable
===============================

`ArrayBuffer` 实例的 **`resizable`** 访问器属性返回此数组缓冲区是否可以调整大小。

尝试一下
----

描述
--

`resizable` 是一个访问器属性，其 set 访问器函数是 `undefined`，这意味着你只能读取该属性。该属性的值在数组创建时就确定了。如果在构造函数中设置了 `maxByteLength` 选项，`resizable` 将返回 `true`；否则，它将返回 `false`。

示例
--

### 使用 resizable

在这个示例中，我们创建了一个 8 字节缓冲区，该缓冲区可调整到的最大长度为 16 字节，然后检查它的 `resizable` 属性，如果 `resizable` 返回 `true` 则调整它的大小：

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

if (buffer.resizable) {
  console.log("缓冲区可以调整大小！");
  buffer.resize(12);
}
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-arraybuffer.prototype.resizable |

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

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

参见
--

* `ArrayBuffer`
* `ArrayBuffer.prototype.maxByteLength`
* `ArrayBuffer.prototype.resize()`


ArrayBuffer.prototype.detached - JavaScript

ArrayBuffer.prototype.detached
==============================

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

`ArrayBuffer` 实例的 **`detached`** 访问器属性返回一个布尔值，指示该缓冲区是否已经分离（传输）。

描述
--

`detached` 属性是一个访问器属性，其 set 访问器函数是 `undefined`，这意味着你只能读取此属性。该属性的值在创建 `ArrayBuffer` 时设置为 `false`。如果 `ArrayBuffer` 已被传输，则该值将变为 `true`，这将使该实例从其底层内存中分离。一旦缓冲区被分离，它就不再可用。

示例
--

### 使用 detached

```js
const buffer = new ArrayBuffer(8);
console.log(buffer.detached); // false
const newBuffer = buffer.transfer();
console.log(buffer.detached); // true
console.log(newBuffer.detached); // false
```

规范
--

| Specification |
| --- |
| ArrayBuffer transfer # sec-get-arraybuffer.prototype.detached |

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

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

参见
--

* `ArrayBuffer`
* `ArrayBuffer.prototype.transfer()`
* `ArrayBuffer.prototype.transferToFixedLength()`


ArrayBuffer.isView() - JavaScript

ArrayBuffer.isView()
====================

**`ArrayBuffer.isView()`** 静态方法判断传入值是否是 `ArrayBuffer` 视图之一，例如类型化数组对象或 `DataView`。

尝试一下
----

语法
--

```js
ArrayBuffer.isView(value)
```

### 参数

`value`

要检查的值。

### 返回值

如果给定参数是 `ArrayBuffer` 视图之一则返回 `true`；否则返回 `false`。

示例
--

### 使用 isView

```js
ArrayBuffer.isView(); // false
ArrayBuffer.isView([]); // false
ArrayBuffer.isView({}); // false
ArrayBuffer.isView(null); // false
ArrayBuffer.isView(undefined); // false
ArrayBuffer.isView(new ArrayBuffer(10)); // false

ArrayBuffer.isView(new Uint8Array()); // true
ArrayBuffer.isView(new Float32Array()); // true
ArrayBuffer.isView(new Int8Array(10).subarray(0, 3)); // true

const buffer = new ArrayBuffer(2);
const dv = new DataView(buffer);
ArrayBuffer.isView(dv); // true
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-arraybuffer.isview |

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

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

参见
--

* JavaScript 类型化数组指南


ArrayBuffer.prototype.maxByteLength - JavaScript

ArrayBuffer.prototype.maxByteLength
===================================

`ArrayBuffer` 实例的 **`maxByteLength`** 访问器属性返回该数组缓冲区可调整到的最大长度（以字节为单位）。

尝试一下
----

描述
--

`maxByteLength` 属性是一个访问器属性，其设置访问器函数为 `undefined`，这意味着你只能读取此属性。该值在构造数组时通过 `ArrayBuffer()` 构造函数的 `maxByteLength` 选项设置，并且不能更改。

如果该 `ArrayBuffer` 已分离，则该属性返回 0。如果该 `ArrayBuffer` 构造时未指定 `maxByteLength` 值，则该属性返回 `ArrayBuffer` 的 `byteLength` 值。

示例
--

### 使用 maxByteLength

在该示例中，我们创建一个 8 字节缓冲区，该缓冲区可调整到的最大长度为 16 字节，然后返回其 `maxByteLength`：

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

buffer.maxByteLength; // 16
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-arraybuffer.prototype.maxbytelength |

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

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

参见
--

* `ArrayBuffer`
* `ArrayBuffer.prototype.byteLength`
* `ArrayBuffer.prototype.resize()`


ArrayBuffer.prototype.byteLength - JavaScript

ArrayBuffer.prototype.byteLength
================================

`ArrayBuffer` 实例的 `byteLength` 访问器属性返回该数组缓冲区的长度（以字节为单位）。

尝试一下
----

描述
--

`byteLength` 属性是一个访问器属性，它的 set 访问器函数是 `undefined`，这意味着你只能读取这个属性。该值在数组创建时确定，并且无法修改。如果这个 `ArrayBuffer` 被分离，则此属性返回 0。

示例
--

### 使用 byteLength

```js
const buffer = new ArrayBuffer(8);
buffer.byteLength; // 8
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-arraybuffer.prototype.bytelength |

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

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

参见
--

* `ArrayBuffer`


ArrayBuffer[@@species] - JavaScript

ArrayBuffer[@@species]
======================

**`ArrayBuffer[@@species]`** 静态访问器属性返回用于构造数组缓冲区方法返回值的构造函数。

**警告：** `@@species` 的存在允许任意代码执行，并可能产生安全漏洞。这也使某些优化变得更加困难。引擎实现者正在调查是否删除此特性。如果可能的话，请避免依赖它。

语法
--

```js
ArrayBuffer[Symbol.species]
```

### 返回值

调用 `get @@species` 的构造函数（`this`）的值。该返回值被用于构造创建新的数组缓冲区的数组缓冲区方法的返回值。

描述
--

`@@species` 访问器属性返回 `ArrayBuffer` 对象的默认构造函数。子类构造函数可以重写它来更改构造函数赋值。基本的默认实现是：

```js
// 用于说明的假设基础实现
class ArrayBuffer {
  static get [Symbol.species]() {
    return this;
  }
}
```

由于这种多态实现，派生子类的 `@species` 也将默认返回构造函数本身。

```js
class SubArrayBuffer extends ArrayBuffer {}
SubArrayBuffer[Symbol.species] === SubArrayBuffer; // true
```

当调用不会修改现有对象，而是返回一个新的数组缓冲区实例数组缓冲区方法（例如，`slice()`）时，对象的 `constructor[@@species]` 将被访问。返回的构造函数将用于构造该数组缓冲区方法的返回值。

示例
--

### 普通对象中的 species

`@@species` 属性返回默认构造函数，即 `ArrayBuffer` 构造函数。

```js
ArrayBuffer[Symbol.species]; // function ArrayBuffer()
```

### 派生对象中的 species

在一个自定义的 `ArrayBuffer` 子类实例中，例如 `MyArrayBuffer`，`MyArrayBuffer` 的 `species` 是 `MyArrayBuffer` 构造函数。但是，你可能希望重写它，以便在派生类方法中返回父类 `ArrayBuffer` 对象：

```js
class MyArrayBuffer extends ArrayBuffer {
  // 重写 MyArrayBuffer species 来返回父类 ArrayBuffer 构造函数
  static get [Symbol.species]() {
    return ArrayBuffer;
  }
}
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-arraybuffer-@@species |

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

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

参见
--

* `ArrayBuffer`
* `Symbol.species`


WeakSet() 构造函数 - JavaScript

WeakSet() 构造函数
==============

**`WeakSet()`** 构造函数创建 `WeakSet` 对象。

语法
--

```js
new WeakSet()
new WeakSet(iterable)
```

**备注：** `WeakSet()` 构造函数只能使用 `new` 调用。不使用 `new` 而直接调用会抛出 `TypeError`。

### 参数

`iterable` 可选

如果传入了一个可迭代对象，这个对象的所有元素都会被添加到新的 `WeakSet` 对象中。`null` 会被视为 `undefined`。

示例
--

### 使用 WeakSet 对象

```js
const ws = new WeakSet();
const foo = {};
const bar = {};

ws.add(foo);
ws.add(bar);

ws.has(foo); // true
ws.has(bar); // true

ws.delete(foo); // 将 foo 从集合中移除
ws.has(foo); // false，foo 已经被移除
ws.has(bar); // true，bar 被保留
```

请注意 `foo !== bar`。它们是相似的对象，*但它们**不是同一个对象***。因此，它们都会被添加到集合中。

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-weakset-constructor |

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

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

参见
--

* `core-js` 中 `WeakSet` 的 polyfill
* `WeakSet`


WeakSet.prototype.delete() - JavaScript

WeakSet.prototype.delete()
==========================

`WeakSet` 实例的 **`delete()`** 方法从该 `WeakSet` 对象中删除指定的元素。

尝试一下
----

语法
--

```js
weakSetInstance.delete(value)
```

### 参数

`value`

要从 `WeakSet` 对象中删除的值。

### 返回值

如果成功在 `WeakSet` 对象中删除了元素，则返回 `true`。如果未在 `WeakSet` 中找到该 `value`，则返回 `false`。如果 `value` 不是对象或非全局注册的符号，则始终返回 `false`。

示例
--

### 使用 delete() 方法

```js
const ws = new WeakSet();
const obj = {};

ws.add(window);

ws.delete(obj); // 返回 false。没有找到要删除的对象。
ws.delete(window); // 返回 true。成功删除。

ws.has(window); // 返回 false。WeakMap 中已经不存在 window 对象。
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-weakset.prototype.delete |

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

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

参见
--

* `WeakSet`
* `WeakSet.prototype.add()`
* `WeakSet.prototype.has()`


WeakSet.prototype.add() - JavaScript

WeakSet.prototype.add()
=======================

`WeakSet` 实例的 **`add()`** 方法在该 `WeakSet` 对象的末尾追加一个新的对象。

尝试一下
----

语法
--

```js
add(value)
```

### 参数

`value`

必须是对象或非全局注册的符号。将要添加到 `WeakSet` 集合中的值。

### 返回值

该 `WeakSet` 对象。

### 异常

`TypeError`

如果 `value` 不是一个对象或非全局注册的符号，则抛出该异常。

示例
--

### 使用 add

```js
const ws = new WeakSet();

ws.add(window); // 将 window 对象添加到 WeakSet

ws.has(window); // true

// WeakSet 只接受对象作为参数
ws.add(1);
// Chrome 中的结果：“TypeError: Invalid value used in weak set”
// Firefox 中的结果：“TypeError: 1 is not a non-null object”
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-weakset.prototype.add |

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

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

参见
--

* `WeakSet`
* `WeakSet.prototype.delete()`
* `WeakSet.prototype.has()`


WeakSet.prototype.has() - JavaScript

WeakSet.prototype.has()
=======================

`WeakSet` 实例的 **`has()`** 方法返回一个布尔值，指示该 `WeakSet` 中指定的对象是否存在。

尝试一下
----

语法
--

```js
has(value)
```

### 参数

`value`

要测试是否在该 `WeakSet` 对象中存在的值。

### 返回值

如果指定的值存在于 `WeakSet` 对象中，则返回 `true`；否则返回 `false`。如果 `value` 不是对象或非全局注册的符号，则始终返回 `false`。

示例
--

### 使用 `has()` 方法

```js
const ws = new WeakSet();
const obj = {};
ws.add(window);

ws.has(window); // 返回 true
ws.has(obj); // 返回 false

// 存储非全局注册的符号
const sym = Symbol("foo");
ws.add(sym);
ws.add(Symbol.iterator);
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-weakset.prototype.has |

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

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

参见
--

* `WeakSet`
* `WeakSet.prototype.add()`
* `WeakSet.prototype.delete()`


Set.prototype.delete() - JavaScript

Set.prototype.delete()
======================

`Set` 实例的 **`delete()`** 方法从该集合中删除指定值，如果该值在集合中。

尝试一下
----

语法
--

```js
setInstance.delete(value)
```

### 参数

`value`

要从 `Set` 中移除的值。

### 返回值

成功删除返回 `true`，否则返回 `false`。

示例
--

### 使用 delete() 方法

```js
const mySet = new Set();
mySet.add("foo");

console.log(mySet.delete("bar")); // 返回 false，不包含 "bar" 这个元素
console.log(mySet.delete("foo")); // 返回 true，删除成功

console.log(mySet.has("foo")); // 返回 false，"foo" 已经成功删除
```

### 从 Set 中删除对象

因为对象是通过引用比较的，所以如果没有对原始对象的引用，就必须通过检查各个属性来删除它们。

```js
const setObj = new Set(); // 创建一个新 set

setObj.add({ x: 10, y: 20 }); // 在 set 中添加对象

setObj.add({ x: 20, y: 30 }); // 在 set 中添加对象

// 删除任何 'x > 10' 的点
setObj.forEach((point) => {
  if (point.x > 10) {
    setObj.delete(point);
  }
});
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.delete |

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

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

参见
--

* `Set`
* `Set.prototype.clear()`