Symbol 常用场景
Symbol
是 ES6 中一个新的原始类型,通过工厂函数创建,不能作为 constructor
创建
const A_symbol = Symbol('description');
复制代码
参数是一个描述,是此 Symbol 的描述,在调用 toString
的时候会出现,没有其他功能。
okay,总结一下 Symbol 大概有以下几种使用场景:
-
作为唯一的对象 key,不会冲突,每个从
Symbol()
返回的symbol值都是唯一的。const MY_KEY = Symbol(); const obj = {}; obj[MY_KEY] = 123; console.log(obj[MY_KEY]); // 123 // 在对象字面量中使用,要带方括号; const MY_KEY = Symbol(); const obj = { [MY_KEY]: 123 }; 复制代码
-
作为私有变量的 key (key for non-public properties)
Symbol
作为属性 key,在某些情况下会 “隐藏”。下面的操作会显示
Symbol
做 key 的 property:Reflect.ownKeys()
;- 通过
[]
访问属性; Object.assign()
;
下面的操作会忽略
Symbol
做 key 的 property:Object.keys()
;Object.getOwnPropertyNames()
;for-in
循环;
当然,我们还有
Private class features
(兼容性堪忧)和_key 命名方案
,可以作为实现私有属性的选项; -
作为系统预留的 key (key for meta-level properties)
例如,根据标准规定,一个对象实现了以
Symbol.iterator
为 key 的属性(属性值符合iterator
规定),就变成了可迭代的对象。const obj = { data: [ 'hello', 'world' ], [Symbol.iterator]() { ··· } }; for (const x of obj) { console.log(x); } 复制代码
当然,还包括一些“well-known-symbols”。
-
表示常量
我们可以使用
Symbol
来表示常量,可以避免出现诸如:混用两个命名不同但数值相同的常量(具体请见这里);
Symbol 的跨域(Crossing realms with symbols)
*这里的 “域” 应该指的是代码作用于,而不是 CORS 里的 “域”。
在看 Symbol
各种资料的时候,我就有一个疑问,如果在两个不同程序里生成 Symbol,并且传输比较,那他们还能保证不重复吗?这里就给出了解释;
不同的域(例如同一个页面中不同的 iframe
)有不同的全局作用域,这样,所有类似 Array
的对象无法跨域,因为它们是引用型的(Objects are compared by identity, but booleans, numbers and strings are compared by value. )。普通的原始类型,如number
、String
等,在跨域时只是传值,所以没有问题。而 Symbol
虽然也是原始类型,但它具有唯一身份(Symbols have individual identities and thus don’t travel across realms as smoothly as other primitive values.),我推测也是一种引用,不能在域之间传递。
不过,我们不是还有 Symbol.iterator
这样的 well-known Symbols
嘛,一个可迭代对象到另一个域中还是可以迭代的,说明 Symbol.iterator
在两个不同域中传递没有问题。这是因为,保留的 Symbol
符号由 JavaScript Engine 负责,以此保证跨域正常。
如果我们想让自定义的 Symbol
也能够跨域,就需要使用 Symbol.for()
一系列 API,它们将参数 map 为 Symbol
,当你在其他域提供同样参数时,会得到同一个 Symbol
。
That all~
参考: