Symbol 是一种特殊的、不可变的数据类型,可以作为对象属性的标识符使用。Symbol 对象是一个 symbol primitive data type 的隐式对象包装器。
symbol 数据类型是一个 primitive data type。
语法
Symbol([description])
参数
description
可选- 可选的,字符串。可用于调试但不能访问符号本身的符号描述。
描述
要创建一个新的基本 symbol,你可以使用一个可选的字符串作为其描述,写Symbol()
.
var sym0 = Symbol(); var sym1 = Symbol("symbol1"); var sym2 = Symbol("symbol2"); var sym3 = Symbol("symbol2");
上面的代码创建三个新的symbols。 注意,Symbol("
symbol2")
不会强制字符串 “symbol2” 成为一个 symbol。它每次都会创建一个新的 symbol:
Symbol("symbol2") === Symbol("symbol2"); // false
下面使用 new
运算符的语法将会抛出一个 TypeError
错误:
var sym = new Symbol(); // TypeError
这会阻止创建一个显式的 Symbol 包装器对象而不是一个 Symbol 值。围绕原始数据类型创建一个显式包装器对象从 ECMAScript 6 开始不再被支持。 然而,现有的原始包装器对象,如 new Boolean、
new String
以及new Number因为遗留原因仍可被创建。
如果你真地想创建一个 Symbol 包装对象(Symbol
wrapper object),你可以使用 Object() 函数:
var sym = Symbol("foo"); typeof sym; // "symbol" var symObj = Object(sym); typeof symObj; // "object"
全局共享的 Symbol
上面的语法使用Symbol()
函数 不会在你的整个代码库中创建一个可用的全局符号。 要创建跨文件可用的symbols,甚至跨域(每个都有它自己的全局作用域) , 使用这个方法Symbol.for()
和 Symbol.keyFor()
从全局symbol的注册处设置和取得symbols。
在对象中查找 Symbol 属性
方法Object.getOwnPropertySymbols()
让你在查找一个给定对象的符号属性时返回一个符号类型的数组。注意,每个初始化的对象都是没有自己的符号属性的,因此这个数组可能为空。除非你已经在对象上设置了符号属性。
属性
Symbol.length
- 长度属性值为1。
- Symbol.name
- 仅Chrome/v8。返回符号描述。
Symbol.prototype
- 描述符号构造函数的原型。
众所周知的符号
除了你自己的符号,JavaScript还内建了一些在ECMAScript 5 之前没有暴露给开发者的符号,它们代表了内部语言行为。这些符号可以使用以下属性访问:
-
迭代 symbols
Symbol.iterator
- 一个返回一个对象默认迭代器的方法。使用
for...of
. -
正则表达式 symbols
Symbol.match
- 一个用于对字符串进行匹配的方法,也用于确定一个对象是否可以作为正则表达式使用。使用
String.prototype.match()
. Symbol.replace
- 一个替换匹配字符串的子串的方法. 使用
String.prototype.replace()
. Symbol.search
- 一个返回一个字符串中与正则表达式相匹配的索引的方法。使用
String.prototype.search()
. Symbol.split
- 一个在匹配正则表达式的索引处拆分一个字符串的方法.。使用
String.prototype.split()
. -
其他 symbols
Symbol.hasInstance
- 一个确定一个构造器对象识别的对象是否为它的实例的方法。使用
instanceof
. Symbol.isConcatSpreadable
- 一个布尔值,表明一个对象是否应该flattened为它的数组元素。使用
Array.prototype.concat()
. Symbol.unscopables
- 拥有和继承属性名的一个对象的值被排除在与环境绑定的相关对象外。
Symbol.species
- 一个用于创建派生对象的构造器函数。.
Symbol.toPrimitive
- 一个将对象转化为基本数据类型的方法。
Symbol.toStringTag
- 用于对象的默认描述的字符串值。使用
Object.prototype.toString()
.
方法
Symbol.for(key)
- 使用给定的key搜索现有符号,如果找到则返回符号。否则将得到一个新的使用给定的key在全局符号注册表中创建的符号。
Symbol.keyFor(sym)
- 为给定符号从全局符号注册表中检索一个共享符号键。
Symbol 原型
所有 Symbol 继承自 Symbol.prototype
.
属性
Symbol.prototype.constructor
- 返回创建实例原型的函数. 默认为
Symbol
函数。
方法
Symbol.prototype.toSource()
- 返回包含
Symbol
对象源码的字符串。覆盖Object.prototype.toSource()
方法。 Symbol.prototype.toString()
- 返回包含Symbol描述符的字符串。 覆盖
Object.prototype.toString()
方法。 Symbol.prototype.valueOf()
- 返回
Symbol
对象的初始值.。覆盖Object.prototype.valueOf()
方法。 Symbol.prototype[@@toPrimitive]
- 返回
Symbol
对象的初始值。
示例
对 symbol 使用 typeof 运算符
typeof
运算符能帮助你识别(标识)symbol
typeof Symbol() === 'symbol'
typeof Symbol('foo') === 'symbol'
typeof Symbol.iterator === 'symbol'
Symbol 类型转换
当使用 symbol 值进行类型转换时需要注意一些事情:
- 尝试将一个 symbol 值转换为一个 number 值时,会抛出一个
TypeError
错误 (e.g.+sym
orsym | 0
). - 使用宽松相等时,
Object(sym) == sym
returnstrue.
- 这会阻止你从一个 symbol 值隐式地创建一个新的 string 类型的属性名。例如,
Symbol("foo") + "bar" 将抛出一个
TypeError
(can't convert symbol to string). - "safer"
String(sym)
conversion works like a call toSymbol.prototype.toString()
with symbols,但是注意new String(sym)
将抛出异常。
Symbols 与 for...in 迭代
Symbols 在 for...in
迭代中不可枚举。另外,Object.getOwnPropertyNames()
不会返回 symbol 对象的属性,但是你能使用 Object.getOwnPropertySymbols()
得到它们。
var obj = {};
obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
obj.d = "d";
for (var i in obj) {
console.log(i); // logs "c" and "d"
}
Symbols 与 JSON.stringify()
当使用 JSON.strIngify() 时以 symbol 值作为键的属性会被完全忽略:
JSON.stringify({[Symbol("foo")]: "foo"});
// '{}'
更多细节,请看 JSON.stringify()
。
Symbol 包装器对象作为属性的键
当一个 Symbol 包装器对象作为一个属性的键时,这个对象将被强制转换为它的包装过的 symbol 值:
var sym = Symbol("foo");
var obj = {[sym]: 1};
obj[sym]; // 1
obj[Object(sym)]; // still 1
技术标准
标准 | 状态 | 注释 |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) Symbol |
Standard | 原始定义 |
ECMAScript Latest Draft (ECMA-262) Symbol |
Living Standard |
浏览器兼容性
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | 38 | 36.0 (36.0) | 未实现 | 25 | 未实现 |
Symbol.iterator (@@iterator) | 38 | 36.0 (36.0) | 未实现 | 25 | 未实现 |
Symbol.unscopables (@@unscopables) | 38 | 未实现 | 未实现 | 25 | 未实现 |
Symbol.match (@@match) | 未实现 | 40.0 (40.0) | 未实现 | 未实现 | 未实现 |
Symbol.species (@@species) | 未实现 | 41.0 (41.0) | 未实现 | 未实现 | 未实现 |
Symbol.toPrimitive (@@toPrimitive) | 未实现 | 44.0 (44.0) | 未实现 | 未实现 | 未实现 |
Other well-known symbols | 未实现 | 未实现 | 未实现 | 未实现 | 未实现 |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | 未实现 | 38 | 36.0 (36.0) | 未实现 | 25 | 未实现 |
Symbol.iterator (@@iterator) | 未实现 | 38 | 36.0 (36.0) | 未实现 | 25 | 未实现 |
Symbol.unscopables (@@unscopables) | 未实现 | 38 | 未实现 | 未实现 | 25 | 未实现 |
Symbol.match (@@match) | 未实现 | 未实现 | 40.0 (40.0) | 未实现 | 未实现 | 未实现 |
Symbol.species (@@species) | 未实现 | 未实现 | 41.0 (41.0) | 未实现 | 未实现 | 未实现 |
Symbol.toPrimitive (@@toPrimitive) | 未实现 | 未实现 | 44.0 (44.0) | 未实现 | 未实现 | 未实现 |
Other well-known symbols | 未实现 | 未实现 | 未实现 | 未实现 | 未实现 | 未实现 |