符号

符号是一个内置对象,其构造函数返回符号 原始的-也称为符号值或者只是一个符号-这保证是独一无二的。符号通常用于向对象添加唯一的属性键,该属性键不会与任何其他代码可能添加到对象中的键冲突,并且对其他代码通常用于访问对象的任何机制都是隐藏的。这使一种形式的软弱封装或弱形式的信息隐藏.

符号()调用保证返回唯一的符号。符号(“键”)调用将始终为给定的值返回相同的符号“密钥”.何时符号(“键”)调用时,如果可以在全局符号注册表中找到具有给定键的符号,则返回该符号。否则,将创建一个新符号,并将其添加到给定键下的全局符号注册表中,然后返回。

描述

要创建新的基本符号,可以编写符号()描述为可选字符串:

js型
const sym1=符号();const sym2=符号(“foo”);const sym3=符号(“foo”);

上面的代码创建了三个新的符号。请注意符号(“foo”)不强制字符串“foo”到符号中。每次都会创建一个新符号:

js型
符号(“foo”)===符号(“foo”);//

使用以下语法新的操作员将抛出类型错误:

js型
const sym=新符号();//类型错误

这会阻止作者创建显式符号包装器对象而不是新的Symbol值,这可能会令人惊讶,因为通常可以围绕原始数据类型创建显式包装器对象(例如,新布尔值,新字符串新号码).

如果你真的想创建一个符号包装器对象,可以使用对象()功能:

js型
const sym=符号(“foo”);sym类型;//“符号”const symObj=对象(sym);symObj的类型;//“对象”

因为符号是唯一具有引用标识的基本数据类型(也就是说,不能两次创建同一个符号),所以它们的行为在某种程度上类似于对象。例如,它们是可回收的垃圾,因此可以存储在WeakMap(弱点地图),弱集,弱点参考、和定案注册表物体。

全局符号注册表中的共享符号

上述语法使用符号()函数将创建一个符号,其值在程序的整个生命周期中保持唯一。要创建跨文件甚至跨领域(每个领域都有自己的全局范围)可用的符号,请使用以下方法符号.for()符号.keyFor()从全局符号注册表中设置和检索符号。

请注意,“全局符号注册表”只是一个虚构的概念,可能与JavaScript引擎中的任何内部数据结构都不对应,即使存在这样的注册表,JavaScript代码也无法使用其内容,除非通过for()键为()方法。

方法符号.for(tokenString)获取字符串键并从注册表返回符号值,而Symbol.keyFor(symbolValue)获取一个符号值并返回与之对应的字符串键。每一个都是另一个的逆键,因此如下所示真的:

js型
Symbol.keyFor(Symbol.for(“tokenString”))===“tokenString”;//真的

因为注册符号可以在任何地方任意创建,所以它们的行为几乎与包装的字符串完全相同。因此,不能保证它们是唯一的,也不能进行垃圾回收。因此,在中不允许注册符号WeakMap(弱点地图),弱集,弱点参考、和定案注册表物体。

众所周知的符号

的所有静态属性符号构造函数是符号本身,其值在领域中是恒定的。它们被称为众所周知的符号,其目的是充当某些内置JavaScript操作的“协议”,允许用户自定义语言的行为。例如,如果构造函数具有具有符号.hasInstance作为其名称,此方法将使用运算符操作员。

在著名的符号之前,JavaScript使用普通属性来实现某些内置操作。例如JSON.stringify格式函数将尝试调用每个对象的到JSON()方法,以及字符串函数将调用对象的toString()值()方法。然而,随着语言中添加了更多的操作,为每个操作指定一个“魔法属性”可能会破坏向后兼容性,并使语言的行为更难推理。众所周知的符号允许自定义从普通代码中“看不见”,而普通代码通常只读取字符串属性。

注:用于使用符号的规范@@<符号名称>表示众所周知的符号。例如,符号.hasInstance写为@@hasInstance(具有实例)、和Array.prototype[Symbol.iterator]()方法将被调用Array.prototype[@@iterator]()。规范中不再使用此符号,但您仍可以在旧文档或讨论中看到它。

众所周知的符号没有垃圾可回收性的概念,因为它们是固定的,并且在程序的整个生命周期中都是唯一的,类似于诸如阵列原型,因此也允许他们进入WeakMap(弱点地图),弱集,弱点参考、和定案注册表物体。

查找对象上的符号特性

方法Object.getOwnPropertySymbols()返回符号数组,并允许您查找给定对象的符号属性。请注意,每个对象都没有自己的Symbol属性进行初始化,因此除非在对象上设置Symbol特性,否则此数组将为空。

施工单位

符号()

返回Symbol类型的基元值。使用调用时引发错误新的.

静态特性

静态属性都是众所周知的符号。在这些符号的描述中,我们将使用“符号.has实例是一种确定……的方法”,但请记住,这是指将此符号作为方法名的对象方法的语义(因为众所周知的符号充当“协议”),而不是描述符号本身的值。

符号.asyncIterator

返回对象的默认AsyncIterator的方法。使用者等待。。。属于.

符号.hasInstance

一种确定构造函数对象是否将对象识别为其实例的方法。使用者运算符.

符号.isConcatSpreadable

一个布尔值,指示对象是否应展平为其数组元素。使用者Array.prototype.concat().

符号标识符

返回对象的默认迭代器的方法。使用者用于。。。属于.

符号匹配

一种与字符串匹配的方法,也用于确定对象是否可以用作正则表达式。使用者String.prototype.match().

Symbol.match全部

返回迭代器的方法,该迭代器生成正则表达式对字符串的匹配。由使用String.prototype.matchAll().

符号.替换

替换字符串中匹配的子字符串的方法。由使用String.protype.replacement().

符号.搜索

返回与正则表达式匹配的字符串中的索引的方法。使用者String.prototype.search().

符号.种类

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

符号.split

在与正则表达式匹配的索引处拆分字符串的方法。使用者String.prototype.split().

符号.to原语

将对象转换为原语值的方法。

符号.to字符串标记

用于对象默认描述的字符串值。使用者Object.prototype.toString().

符号.不透明度

对象值,其自身和继承的属性名称被排除在具有关联对象的环境绑定。

静态方法

符号.for()

使用给定的钥匙并在找到时返回。否则将创建一个新符号并注册到钥匙.

符号.keyFor()

从给定符号的全局符号注册表检索共享符号键。

实例属性

这些属性定义于符号.原型并由所有人共享符号实例。

符号.原型.结构

创建实例对象的构造函数。对于符号实例,初始值为符号构造函数。

符号.原型.说明

包含符号描述的只读字符串。

Symbol.prototype[Symbol.toStringTag]

的初始值[Symbol.toStringTag]属性是字符串“符号”。此属性用于Object.prototype.toString()然而,因为符号也有自己的toString()方法,除非调用Object.prototype.toString.call()符号为这个Arg.

实例方法

示例

将typeof运算符与符号一起使用

这个类型操作员可以帮助您识别符号。

js型
符号类型()===“符号”;符号类型(“foo”)===“Symbol”;类型Symbol.iterator===“Symbol”;

符号类型转换

处理符号的类型转换时需要注意的一些事项。

  • 尝试将符号转换为数字时类型错误将被抛出(例如。+sym(对称)符号|0).
  • 使用松散等式时,对象(sym)==sym收益真的.
  • 符号(“foo”)+“bar”抛出一个类型错误(无法将符号转换为字符串)。例如,这可以防止您从Symbol无声地创建新的字符串属性名称。
  • 这个“更安全”字符串(sym)转换就像打电话给Symbol.protype.toString()带有符号,但请注意新字符串(sym)将投掷。

符号和用于。。。在迭代中

符号在中不可枚举用于。。。在里面迭代。此外,对象.getOwnPropertyNames()不会返回Symbol对象属性,但可以使用Object.getOwnPropertySymbols()来拿这些。

js型
常量对象={};obj[符号(“a”)]=“a”;obj[Symbol.for(“b”)]=“b”;obj[“c”]=“c”;obj.d=“d”;for(obj中的常量i){控制台.log(i);}//“c”“d”

符号和JSON.stringify()

使用时将完全忽略符号键控属性JSON.stringify():

js型
JSON.stringify({[符号(“foo”)]:“foo“});// '{}'

有关更多详细信息,请参阅JSON.stringify().

作为属性键的符号包装器对象

当Symbol包装器对象用作属性键时,此对象将被强制为其包装的Symbol:

js型
const sym=符号(“foo”);常量对象={[sym]:1};对象[符号];//1obj[对象(sym)];//仍然是1

规格

规范
ECMAScript语言规范
#秒符号对象

浏览器兼容性

BCD表仅在浏览器中加载

另请参见