recursal/MDN huggingface dataset:
Function.prototype[@@hasInstance]()
===================================

`Function` 实例的 **`[@@hasInstance]()`** 方法指定确定构造函数是否将对象识别为其实例的默认过程。它由 `instanceof` 运算符调用。

语法
--


```js
func[Symbol.hasInstance](value)
```

### 参数

`value`

要测试的对象，原始值始终返回 `false`。

### 返回值

如果 `func.prototype` 在 `value` 的原型链中，则返回 `true`，否则返回 `fals`；如果 `value` 不是一个对象或 `this` 不是一个函数，则始终返回 `false`。如果 `this` 是一个绑定函数，则返回对 `value` 和底层目标函数进行 `instanceof` 测试的结果。

### 异常

`TypeError`

如果 `this` 不是绑定函数且 `this.prototype` 不是对象，则会抛出此异常。

描述
--

`instanceof` 运算符在右操作数存在 `@@hasInstance()` 方法时会调用该方法。由于所有函数默认继承自 `Function.prototype`，它们都会具有 `[@@hasInstance]()` 方法，因此大多数情况下，`Function.prototype[@@hasInstance]` 方法指定了右操作数为函数时 `instanceof` 的行为。该方法实现了 `instanceof` 运算符的默认行为（当 `constructor` 没有 `@@hasInstance` 方法时使用相同算法）。

与大多数方法不同，`Function.prototype[@@hasInstance]()` 属性是不可配置且不可写的。这是一个安全特性，用于防止绑定函数的底层目标函数被获取。请参考这个 StackOverflow 回答中的示例。

示例
--

### 恢复默认的 instanceof 行为

你很少需要直接调用这个方法。相反，这个方法是由 `instanceof` 运算符调用的。通常情况下，你应该期望这两种结果是等价的。


```js
class Foo {}
const foo = new Foo();
console.log(foo instanceof Foo === Foo[Symbol.hasInstance](foo)); // true
```


如果你想调用默认的 `instanceof` 行为，但不确定构造函数是否已经重写了 `[@@hasInstance]()` 方法，那么你可以使用这个方法。


```js
class Foo {
  static [Symbol.hasInstance](value) {
    // 自定义实现
    return false;
  }
}

const foo = new Foo();
console.log(foo instanceof Foo); // false
console.log(Function.prototype[Symbol.hasInstance].call(Foo, foo)); // true
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-function.prototype-@@hasinstance |

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

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

参见
--

* `instanceof`
* `Symbol.hasInstance`
Function.prototype.prototype
============================

当 `Function` 实例作为构造函数与 `new` 运算符一起使用时，该实例的 **`prototype`** 数据属性将用作新对象的原型。

**备注：** 并不是所有的 `Function` 对象都拥有 `prototype` 属性——参见描述。

值
-

一个对象。

| `Function.prototype.prototype` 的属性特性 |
| --- |
| 可写 | 是 |
| 可枚举 | 否 |
| 可配置 | 否 |

**备注：** 类的 `prototype` 属性是不可写的。

描述
--

在使用 `new` 运算符调用函数时，构造函数的 `prototype` 属性将成为新对象的原型。


```js
function Ctor() {}
const inst = new Ctor();
console.log(Object.getPrototypeOf(inst) === Ctor.prototype); // true
```


关于构造函数的 `prototype` 属性与结果对象的原型之间的相互作用，你可以查看继承与原型链来了解更多。

一个具有 `prototype` 属性的函数也并不代表其有资格作为构造函数。例如，function\* 拥有 `prototype` 属性，但它不能通过 `new` 运算符来调用。


```js
async function\* asyncGeneratorFunction() {}
function\* generatorFunction() {}
```


反之，生成器函数通常在它们不被 `new` 运算符调用的时候被用到它们的 `prototype` 属性。 `prototype` 属性会作为返回的 `Generator` 对象的原型。

另外，一些函数也可能在通过 `new` 运算符调用的情况下无条件抛出，即便它们可能具有 `prototype`。例如，`Symbol()` 和 `BigInt()` 函数会在它们通过 `new` 运算符来调用时抛出，因为 `Symbol.prototype` and `BigInt.prototype` 只是用来为原始值提供方法的，这时不应该直接构建包装器对象。

下列的函数不具有 `prototype` 属性，因此不能成为构造函数，即便后续手动赋予了 `prototype` 属性：


```js
const method = { foo() {} }.foo;
const arrowFunction = () => {};
async function asyncFunction() {}
```


下列则可以成为合法的构造函数，因为它们具有 `prototype`：


```js
class Class {}
function fn() {}
```


绑定函数不具有 `prototype` 属性，但是可能是可构造的。当它被构造的时候，目标函数将会被构造，如果目标函数是可构造的，将会返回一个普通的实例。


```js
const boundFunction = function () {}.bind(null);
```


默认情况下，函数的 `prototype` 是一个普通的对象。这个对象具有一个属性：`constructor`。它是对这个函数本身的一个引用。 `constructor` 属性是可编辑、可配置但不可枚举的。

如果函数的 `prototype` 被赋予了 `Object` 以外的值，则当它被 `new` 运算符调用时，返回对象的原型将会指向 `Object.prototype`。（换句话说，`new` 运算符会忽略它的 `prototype` 属性并构造一个普通对象。）


```js
function Ctor() {}
Ctor.prototype = 3;
console.log(Object.getPrototypeOf(new Ctor()) === Object.prototype); // true
```

示例
--

### 通过修改原型的属性来修改所有实例的原型


```js
function Ctor() {}
const p1 = new Ctor();
const p2 = new Ctor();
Ctor.prototype.prop = 1;
console.log(p1.prop); // 1
console.log(p2.prop); // 1
```

### 将非函数属性添加到类的原型中

公有类字段会为每一个实例都添加属性。类方法可以在原型中定义*函数*属性。但是，无法将非函数属性添加到原型中。假如你希望在所有实例之间共享静态数据（例如，`Error.prototype.name` 在所有 Error 类的实例中都是相同的），那么你可以在类的原型中进行手动添加。


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

Dog.prototype.species = "dog";

console.log(new Dog("Jack").species); // "dog"
```


使用静态初始化块 (en-US)可以让这个操作更符合直觉。这些块会在类初始化的时候进行调用。


```js
class Dog {
  static {
    Dog.prototype.species = "dog";
  }
  constructor(name) {
    this.name = name;
  }
}

console.log(new Dog("Jack").species); // "dog"
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-function-instances-prototype |

参见
--

* `Function`
* 继承与原型链
Function：length
===============

`Function` 实例的 **`length`** 数据属性表示函数期望的参数数量。

尝试一下
----

值
-

一个数字。

| `Function：length` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 是 |

描述
--

一个 `Function` 对象的 `length` 属性表示函数期望的参数个数，即形参的个数。这个数字不包括剩余参数，只包括在第一个具有默认值的参数之前的参数。相比之下，`arguments.length` 是局限于函数内部的，它提供了实际传递给函数的参数个数。

`Function` 构造函数本身就是一个 `Function` 对象。它的 `length` 数据属性的值为 `1`。

由于历史原因，`Function.prototype` 本身是可调用的。`Function.prototype` 的 `length` 属性的值为 `0`。

示例
--

### 使用 function length


```js
console.log(Function.length); // 1

console.log((() => {}).length); // 0
console.log(((a) => {}).length); // 1
console.log(((a, b) => {}).length); // 2，依此类推

console.log(((...args) => {}).length);
// 0，剩余参数不计算在内

console.log(((a, b = 1, c) => {}).length);
// 1，只计算第一个具有默认值的参数之前的参数
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-function-instances-length |

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

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

参见
--

* `Function`
Function.prototype.caller
=========================

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

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

**备注：** 在严格模式下，访问函数的 `caller` 属性会抛出错误——该 API 已被移除且没有替代品。这是为了防止代码能够“遍历堆栈”，这既存在安全风险，也严重限制了内联和尾调用优化等优化的可能性。如需更多解释，请阅读 arguments.callee 的弃用原因。

`Function` 实例的 **`caller`** 访问器属性返回调用该函数的函数。对于严格模式、箭头函数、异步函数和生成器函数来说，访问 `caller` 属性会抛出 `TypeError`。

描述
--

如果函数 `f` 是在全局作用域内调用的，则 `f.caller` 的值为 `null`；否则它就是调用 `f` 的函数。如果调用 `f` 的函数是一个严格模式函数，则 `f.caller` 的值也是 `null`。

请注意，ECMAScript 规范规定的唯一行为是 `Function.prototype` 具有一个初始的 `caller` 访问器，无论是 `get` 还是 `set` 请求，它都会无条件地抛出 `TypeError`（称为“毒丸访问器”）。而且引擎实现不允许改变此语义，除非是非严格的普通函数。在这种情况下，它不能具有严格模式函数的值。`caller` 属性的实际行为如果不是抛出错误，则该行为是由实现定义的。例如，Chrome 将其定义为自有数据属性，而 Firefox 和 Safari 扩展了初始的毒丸访问器 `Function.prototype.caller`，以特殊处理非严格模式的函数的 `this` 值。


```js
(function f() {
  if (Object.hasOwn(f, "caller")) {
    console.log(
      "caller 是一个自有属性，具有描述符",
      Object.getOwnPropertyDescriptor(f, "caller"),
    );
  } else {
    console.log(
      "f 没有名为 caller 的自有属性。尝试获取 f.[[Prototype]].caller",
    );
    console.log(
      Object.getOwnPropertyDescriptor(
        Object.getPrototypeOf(f),
        "caller",
      ).get.call(f),
    );
  }
})();

// 在 Chrome 中：
// caller 是一个自有属性，具有描述符 {value: null, writable: false, enumerable: false, configurable: false}

// 在 Firefox 中：
// f 没有名为 caller 的自有属性。尝试获取 f.[[Prototype]].caller
// null
```


此属性取代了 `arguments` 对象的已弃用的 `arguments.caller` 属性。

出于安全原因，特殊属性 `__caller__` 已被移除，它返回调用者的激活对象，从而允许重建堆栈。

示例
--

### 检查函数 caller 属性的值

以下代码检查函数的 `caller` 属性的值。


```js
function myFunc() {
  if (myFunc.caller === null) {
    return "该函数是从顶层调用的！";
  } else {
    return `该函数的调用者是 ${myFunc.caller}`;
  }
}
```

### 重建调用堆栈和递归

请注意，在递归的情况下，你不能使用该属性重建调用堆栈。参考以下示例：


```js
function f(n) {
  g(n - 1);
}
function g(n) {
  if (n > 0) {
    f(n);
  } else {
    stop();
  }
}
f(2);
```


当调用 `stop()` 时，调用堆栈将是：
```

f(2) -> g(1) -> f(1) -> g(0) -> stop()
```


以下是条件表达式为真：


```js
stop.caller === g && f.caller === g && g.caller === f;
```


因此，如果你尝试像这样在 `stop()` 函数中获取堆栈跟踪：


```js
let f = stop;
let stack = "Stack trace:";
while (f) {
  stack += `\n${f.name}`;
  f = f.caller;
}
```


循环永远不会停止。

### 严格模式下的 caller

如果调用者是严格模式函数，则 `caller` 的值为 `null`。


```js
function callerFunc() {
  calleeFunc();
}

function strictCallerFunc() {
  "use strict";
  calleeFunc();
}

function calleeFunc() {
  console.log(calleeFunc.caller);
}

(function () {
  callerFunc();
})();
// 输出 [Function: callerFunc]

(function () {
  strictCallerFunc();
})();
// 输出 null
```

规范
--

不属于任何标准。

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

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

参见
--

* `Function.prototype.name`
* `arguments`
Symbol.unscopables
==================

**`Symbol.unscopables`** 指用于指定对象值，其对象自身和继承的从关联对象的 with 环境绑定中排除的属性名称。

尝试一下
----

描述
--

可以在任何对象上定义 `@@unscopables` symbol (`Symbol.unscopables`)，用于排除属性名称并与 `with` 环境绑定在一起作为词法变量公开。请注意，如果使用 Strict mode，语句将不可用，并且可能也不需要 symbol。

在 `unscopables` 对象上设置属性为 true，将使其 *unscopable* 并且因此该属性也将不会在词法环境变量中出现。如果设置属性为 `false` ，则将使其可 `scopable` 并且该属性会出现在词法环境变量中。

| `Symbol.unscopables` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

示例
--

下列的代码可兼容 ES5 及以下版本。然而，在 ECMAScript 2015 (ES6) 或其后续版本中，`Array.prototype.keys()` 方法才会出现。意味着内部 `with` 环境“关键字”存在该方法，但变量中不会存在。也就是说，当 `unscopable`s symbol 被展示时，内置的`unscopables` 设置是由 `Array.prototype[@@unscopables]` 展示并实现的，一些 Array 的方法 将作为 scoped 放入 `with` 语句中。


```js
var keys = [];

with (Array.prototype) {
  keys.push("something");
}

Object.keys(Array.prototype[Symbol.unscopables]);
// ["copyWithin", "entries", "fill", "find", "findIndex",
// "includes", "keys", "values"]
```


你也可以为你自己的对象设置 `unscopables` 。


```js
var obj = {
  foo: 1,
  bar: 2,
};

obj[Symbol.unscopables] = {
  foo: false,
  bar: true,
};

with (obj) {
  console.log(foo); // 1
  console.log(bar); // ReferenceError: bar is not defined
}
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.unscopables |

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

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

参见
--

* `Array.prototype[@@unscopables]`
* `with` 语句（在严格模式中不可用）
Symbol.toPrimitive
==================

**`Symbol.toPrimitive`** 是内置的 symbol 属性，其指定了一种接受首选类型并返回对象原始值的表示的方法。它被所有的强类型转换制算法优先调用。

尝试一下
----

| `Symbol.toPrimitive` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

描述
--

在 `Symbol.toPrimitive` 属性（用作函数值）的帮助下，对象可以转换为一个原始值。该函数被调用时，会被传递一个字符串参数 `hint`，表示要转换到的原始值的预期类型。`hint` 参数的取值是 `"number"`、`"string"` 和 `"default"` 中的任意一个。

`"number"` hint 用于强制数字类型转换算法。`"string"` hint 用于强制字符串类型转换算法。`"default"` hint 用于强制原始值转换算法。`hint` 仅是作为首选项的偏弱的信号提示，实现时，可以自由忽略它（就像 `Symbol.prototype[@@toPrimitive]()` 一样）。该语言不会在 `hint` 和结果类型之间强制校正，尽管 `[@@toPrimitive]()` 必须返回一个原始值，否则将抛出 `TypeError`。

没有 `@@toPrimitive` 属性的对象通过以不同的顺序调用 `valueOf()` 和 `toString()` 方法将其转换为原始值，这在强制类型转换部分进行了更详细的解释。`@@toPrimitive` 允许完全控制原始转换过程。例如，`Date.prototype[@@toPrimitive]` 将 `"default"` 视为 `"string"` 并且调用 `toString()` 而不是 `valueOf()`。`Symbol.prototype[@@toPrimitive]` 忽略 hint，并总是返回一个 symbol，这意味着即使在字符串上下文中，也不会调用 `Symbol.prototype.toString()`，并且 `Symbol` 对象必须始终通过 `String()` 显式转换为字符串。

示例
--

### 修改从对象转换的原始值

以下示例描述了 `Symbol.toPrimitive` 属性如何修改从对象转换的原始值。


```js
// 一个没有提供 Symbol.toPrimitive 属性的对象，参与运算时的输出结果。
const obj1 = {};
console.log(+obj1); // NaN
console.log(`${obj1}`); // "[object Object]"
console.log(obj1 + ""); // "[object Object]"

// 接下面声明一个对象，手动赋予了 Symbol.toPrimitive 属性，再来查看输出结果。
const obj2 = {
  [Symbol.toPrimitive](hint) {
    if (hint === "number") {
      return 10;
    }
    if (hint === "string") {
      return "hello";
    }
    return true;
  },
};
console.log(+obj2); // 10 — hint 参数值是 "number"
console.log(`${obj2}`); // "hello" — hint 参数值是 "string"
console.log(obj2 + ""); // "true" — hint 参数值是 "default"
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.toprimitive |

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

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

参见
--

* `Date.prototype[@@toPrimitive]()`
* `Symbol.prototype[@@toPrimitive]()`
* `Object.prototype.toString()`
* `Object.prototype.valueOf()`
Symbol() 构造函数
=============

**`Symbol()`** 构造函数返回一个 **symbol** 类型的值，但是它并不完全支持构造函数的语法，因为它不支持 `new Symbol()` 语法，也无法被子类化。它可以作为 `class` 定义中 `extends` 子句的值使用，但对它进行 `super` 调用将会导致异常。

尝试一下
----

语法
--


```js
Symbol()
Symbol(description)
```


**备注：** `Symbol()` 只能在没有 `new` 的情况下调用，尝试用 `new` 构造会抛出 `TypeError`。

参数
--

`description` 可选

一个字符串，用来表示 symbol 的描述，可以用于调试，但不能直接访问 symbol 自身。

示例
--

### 创建 symbol

要创建一个新的原始 symbol，你可以传递一个可选的字符串作为 `description` 参数来创建 `Symbol()`：


```js
const sym1 = Symbol();
const sym2 = Symbol("foo");
const sym3 = Symbol("foo");
```


上面的代码创建了三个新的 symbol，注意 `Symbol("foo")` 不会将字符串 `"foo"` 强制转换成 symbol，而是每次总是创建一个新的 symbol：


```js
Symbol("foo") === Symbol("foo"); // false
```

### new Symbol()

下面带有 `new` 运算符的语法将会抛出一个 `TypeError`：


```js
const sym = new Symbol(); // TypeError
```


这一限制是为了防止开发人员创建一个显式的 `Symbol` 包装对象，而不是一个新的 symbol 值。这可能会让人感到困扰，因为在通常情况下，可以创建基本数据类型的显式包装对象（例如 `new Boolean`、`new String` 和 `new Number`）。

如果你真的想创建一个 `Symbol` 包装器对象，你可以使用 `Object()` 函数：


```js
const sym = Symbol("foo");
const symObj = Object(sym);
typeof sym; // "symbol"
typeof symObj; // "object"
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol-constructor |

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

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

参见
--

* `core-js` 中 `Symbol` 的 Polyfill
Symbol.species
==============

知名的 **`Symbol.species`** 是个函数值属性，其被构造函数用以创建派生对象。

尝试一下
----

| `Symbol.species` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

描述
--

species 访问器属性允许子类覆盖对象的默认构造函数。

示例
--

你可能想在扩展数组类 `MyArray` 上返回 `Array` 对象。例如，当使用例如 `map()` 这样的方法返回默认的构造函数时，你希望这些方法能够返回父级的 Array 对象，以取代 `MyArray` 对象。`Symbol.species` 允许你这么做：


```js
class MyArray extends Array {
  // 覆盖 species 到父级的 Array 构造函数上
  static get [Symbol.species]() {
    return Array;
  }
}
var a = new MyArray(1, 2, 3);
var mapped = a.map((x) => x \* x);

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

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.species |

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

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

参见
--

* `Map[@@species]`
* `Set[@@species]`
Symbol.split
============

**`Symbol.split`** 指向 一个正则表达式的索引处分割字符串的方法。这个方法通过 `String.prototype.split()` 调用。

详情请参阅`RegExp.prototype[@@split]()` 和`String.prototype.split()`.

尝试一下
----

| `Symbol.split` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

示例
--

[Symbol.split] 指向‘aba’.split(/a/)


```js
/a/[Symbol.split]("aba", 3);
```


"dayinlove".split(exp) 调用 [Symbol.split](str) 处理，并把实参"dayinlove"传给形参 str


```js
var exp = {
  pat: "in",
  [Symbol.split](str) {
    return str.split(this.pat);
  },
};

"dayinlove".split(exp);
//["day", "love"]
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.split |

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

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

参阅
--

* `Symbol.match`
* `Symbol.replace`
* `Symbol.search`
* `RegExp.prototype[@@split]()`
Symbol.prototype.description
============================

**`description`** 是一个只读属性，它会返回 `Symbol` 对象的可选描述的字符串。

尝试一下
----

语法
--
```

Symbol('myDescription').description;
Symbol.iterator.description;
Symbol.for('foo').description;
```

描述
--

`Symbol` 对象可以通过一个可选的描述创建，可用于调试，但不能用于访问 symbol 本身。`Symbol.prototype.description` 属性可以用于读取该描述。与 `Symbol.prototype.toString()` 不同的是它不会包含 "`Symbol()`" 的字符串。具体请看实例。

示例
--


```js
Symbol("desc").toString(); // "Symbol(desc)"
Symbol("desc").description; // "desc"
Symbol("").description; // ""
Symbol().description; // undefined

// 内置通用（well-known）symbol
Symbol.iterator.toString(); // "Symbol(Symbol.iterator)"
Symbol.iterator.description; // "Symbol.iterator"

// global symbols
Symbol.for("foo").toString(); // "Symbol(foo)"
Symbol.for("foo").description; // "foo"
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.prototype.description |

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

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

参见
--

* `Symbol.prototype.toString()`
* Polyfill: https://npmjs.com/symbol.prototype.description
Symbol.match
============

**`Symbol.match`** 指定了匹配的是正则表达式而不是字符串。`String.prototype.match()` 方法会调用此函数。

尝试一下
----

描述
--

此函数还用于标识对象是否具有正则表达式的行为。比如， `String.prototype.startsWith()`，`String.prototype.endsWith()` 和 `String.prototype.includes()` 这些方法会检查其第一个参数是否是正则表达式，是正则表达式就抛出一个`TypeError`。现在，如果 `match` symbol 设置为 `false`（或者一个 假值），就表示该对象不打算用作正则表达式对象。

| `Symbol.match` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

示例
--

### 禁止表达式检查

下面代码会抛出一个 `TypeError`：


```js
"/bar/".startsWith(/bar/);

// Throws TypeError，因为 /bar/ 是一个正则表达式
// 且 Symbol.match 没有修改。
```


但是，如果你将 `Symbol.match` 置为 `false`，使用 `match` 属性的表达式检查会认为该对象不是正则表达式对象。`startsWith` 和 `endsWith` 方法将不会抛出 `TypeError`。


```js
var re = /foo/;
re[Symbol.match] = false;
"/foo/".startsWith(re); // true
"/baz/".endsWith(re); // false
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.match |

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

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

参见
--

* `Symbol.replace`
* `Symbol.search`
* `Symbol.split`
* `RegExp.prototype[@@match]()`
Symbol.for()
============

**`Symbol.for(key)`** 方法会根据给定的键 `key`，来从运行时的 symbol 注册表中找到对应的 symbol，如果找到了，则返回它，否则，新建一个与该键关联的 symbol，并放入全局 symbol 注册表中。

语法
--
```

Symbol.for(key);
```

### 参数

key

一个字符串，作为 symbol 注册表中与某 symbol 关联的键（同时也会作为该 symbol 的描述）。

### 返回值

返回由给定的 key 找到的 symbol，否则就是返回新创建的 symbol。

描述
--

和 `Symbol()` 不同的是，用 `Symbol.for()` 方法创建的的 symbol 会被放入一个全局 symbol 注册表中。`Symbol.for() 并不是每次都会创建一个新的 symbol`，它会首先检查给定的 key 是否已经在注册表中了。假如是，则会直接返回上次存储的那个。否则，它会再新建一个。

### 全局 symbol 注册表

symbol 注册表中的记录结构：

| 字段名 | 字段值 |
| --- | --- |
| [[key]] | 一个字符串，用来标识每个 symbol |
| [[symbol]] | 存储的 symbol 值 |

示例
--


```js
Symbol.for("foo"); // 创建一个 symbol 并放入 symbol 注册表中，键为 "foo"
Symbol.for("foo"); // 从 symbol 注册表中读取键为"foo"的 symbol

Symbol.for("bar") === Symbol.for("bar"); // true，证明了上面说的
Symbol("bar") === Symbol("bar"); // false，Symbol() 函数每次都会返回新的一个 symbol

var sym = Symbol.for("mario");
sym.toString();
// "Symbol(mario)"，mario 既是该 symbol 在 symbol 注册表中的键名，又是该 symbol 自身的描述字符串
```


为了防止冲突，最好给你要放入 symbol 注册表中的 symbol 带上键前缀。


```js
Symbol.for("mdn.foo");
Symbol.for("mdn.bar");
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.for |

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

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

参见
--

* `Symbol.keyFor()`
Symbol.search
=============

`Symbol.search` 指定了一个搜索方法，这个方法接受用户输入的正则表达式，返回该正则表达式在字符串中匹配到的下标，这个方法由以下的方法来调用 `String.prototype.search()`。

更多信息请参见 `RegExp.prototype[@@search]()` 和`String.prototype.search()`.

| `Symbol.search` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

案例
--

### 自定义字符串搜索
```

class caseInsensitiveSearch {
  constructor(value) {
    this.value = value.toLowerCase();
  }
  [Symbol.search](string) {
    return string.toLowerCase().indexOf(this.value);
  }
}

console.log('foobar'.search(new caseInsensitiveSearch('BaR')));
// expected output: 3
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.search |

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

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

参见
--

* `Symbol.match`
* `Symbol.replace`
* `Symbol.split`
* `RegExp.prototype[@@search]()`
Symbol.replace
==============

**`Symbol.replace`** 这个属性指定了当一个字符串替换所匹配字符串时所调用的方法。`String.prototype.replace()` 方法会调用此方法。

更多信息，详见 `RegExp.prototype[@@replace]()` 和 `String.prototype.replace()`。

尝试一下
----

| `Symbol.replace` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

Specifications
--------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.replace |

Browser compatibility
---------------------

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

See also
--------

* `Symbol.match`
* `Symbol.search`
* `Symbol.split`
* `RegExp.prototype[@@replace]()`
Symbol.prototype.valueOf()
==========================

概述
--

**`valueOf()`** 方法返回当前 symbol 对象所包含的 symbol 原始值。

语法
--
```

symbol.valueOf();
```

描述
--

在 JavaScript 中，虽然大多数类型的对象在某些操作下都会自动的隐式调用自身的 `valueOf()` 方法或者 `toString()` 方法来将自己转换成一个原始值，但 symbol 对象不会这么干，symbol 对象无法隐式转换成对应的原始值：


```js
Object(Symbol("foo")) + "bar";
// TypeError: can't convert symbol object to primitive
// 无法隐式的调用 valueOf() 方法

Object(Symbol("foo")).valueOf() + "bar";
// TypeError: can't convert symbol to string
// 手动调用 valueOf() 方法，虽然转换成了原始值，但 symbol 原始值不能转换为字符串

Object(Symbol("foo")).toString() + "bar";
// "Symbol(foo)bar"，需要手动调用 toString() 方法才行
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.prototype.valueof |

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

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

参见
--

* `Object.prototype.valueOf()`
Symbol.prototype[@@toPrimitive]
===============================

**`[@@toPrimitive]()`** 方法可将 Symbol 对象转换为原始值。

语法
--


```js
Symbol()[Symbol.toPrimitive](hint)
```

### 返回值

指定的 `Symbol` 对象的原始值。

描述
--

`hint` 参数未使用时，`Symbol` 的 `[@@toPrimitive]()` 方法返回 Symbol 对象的原始值作为数据类型返回。

JavaScript 调用 `[@@toPrimitive]()` 方法将一个对象转换为原始值表示。你不需要自己调用 `[@@toPrimitive]()` 方法；当对象需要被转换为原始值时，JavaScript 会自动地调用该方法。

示例
--

### 使用 @@toPrimitive


```js
const sym = Symbol("example");
sym === sym[Symbol.toPrimitive](); // true
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.prototype-@@toprimitive |

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

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

参见
--

* `Symbol.toPrimitive`
Symbol.asyncIterator
====================

**`Symbol.asyncIterator`** 符号指定了一个对象的默认异步迭代器。如果一个对象设置了这个属性，它就是异步可迭代对象，可用于`for await...of`循环。

描述
--

`Symbol.asyncIterator` 是一个用于访问对象的`@@asyncIterator`方法的内建符号。一个异步可迭代对象必须要有`Symbol.asyncIterator`属性。

| `Symbol.asyncIterator` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

示例
--

### 自定义异步可迭代对象

你可以通过设置`[Symbol.asyncIterator]`属性来自定义异步可迭代对象。


```js
const myAsyncIterable = new Object();
myAsyncIterable[Symbol.asyncIterator] = async function\* () {
  yield "hello";
  yield "async";
  yield "iteration!";
};

(async () => {
  for await (const x of myAsyncIterable) {
    console.log(x);
    // expected output:
    // "hello"
    // "async"
    // "iteration!"
  }
})();
```

### 内建异步可迭代对象

目前没有默认设定了`[Symbol.asyncIterator]`属性的 JavaScript 内建的对象。不过，WHATWG（网页超文本应用技术工作小组）Streams 会被设定为第一批异步可迭代对象，`[Symbol.asyncIterator]` 最近已在设计规范中落地。

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.asynciterator |

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

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

参见
--

* Iteration protocols
* for await... of
Symbol.isConcatSpreadable
=========================

内置的 **`Symbol.isConcatSpreadable`** 符号用于配置某对象作为 `Array.prototype.concat()` 方法的参数时是否展开其数组元素。

尝试一下
----

描述
--

`@@isConcatSpreadable` 符号 (`Symbol.isConcatSpreadable`) 可以直接定义为对象属性或继承而来，它是布尔类型。它可以控制数组或类似数组（array-like）的对象的行为：

* 对于数组对象，默认情况下，用于 concat 时，会按数组元素展开然后进行连接（数组元素作为新数组的元素）。重置`Symbol.isConcatSpreadable`可以改变默认行为。
* 对于类似数组的对象，用于 concat 时，该对象整体作为新数组的元素，重置`Symbol.isConcatSpreadable`可改变默认行为。

| `Symbol.isConcatSpreadable` 的属性特性 |
| --- |
| 可写 | 否 |
| 可枚举 | 否 |
| 可配置 | 否 |

示例
--

### 数组

默认情况下，`Array.prototype.concat()` 展开其元素连接到结果中：


```js
var alpha = ["a", "b", "c"],
  numeric = [1, 2, 3];

var alphaNumeric = alpha.concat(numeric);

console.log(alphaNumeric); // 结果：['a', 'b', 'c', 1, 2, 3]
```


设置`Symbol.isConcatSpreadable`为`false`：


```js
var alpha = ["a", "b", "c"],
  numeric = [1, 2, 3];

numeric[Symbol.isConcatSpreadable] = false;
var alphaNumeric = alpha.concat(numeric);

console.log(alphaNumeric); // 结果：['a', 'b', 'c', [1, 2, 3] ]
```

### Array-like 对象

对于类数组 (array-like) 对象，默认不展开。期望展开其元素用于连接，需要设置 `Symbol.isConcatSpreadable` 为 true：


```js
var x = [1, 2, 3];

var fakeArray = {
  [Symbol.isConcatSpreadable]: true,
  length: 2,
  0: "hello",
  1: "world",
};

x.concat(fakeArray); // [1, 2, 3, "hello", "world"]
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-symbol.isconcatspreadable |

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

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

参考
--

* `Array.prototype.concat()`