什么是Symbol
类型
Symbol
是一种新的原始数据类型, 表示独一无二的值
解决痛点: 你使用了他人的一个对象, 但又想给这个对象添加新的方法(mixin模式), 新的方法的名字就有可能与现有的方法产生冲突. 如果有一种机制, 保证每个属性的名字都是独一无二的就好了, 这样就能从根本上防止属性名的冲突
使用方式
Symbol
值通过Symbol
函数生成. 这就是说, 对象的属性名现在可以有两种类型, 一种是原来的字符串, 另一种是现在新增的Symbol
类型.凡是属性名属于Symbol
类型都是独一无二的, 可以保证不会与其他属性的名称产生冲突.
let s = Symbol();
typeof s
- Note:
-
Symbol
函数前不能使用new
命令, 否则会报错.这是因为生成的Symbol是一种原始类型的值, 而不是一个对象.也就是说, 由于Symbol值不是对象, 所以不能添加属性. -
Symbol
值不能与其他类型的值进行运算, 否则会报错 -
Symbol
值可以转换为bool
和string
类型, 但是不能转换为number
类型 -
Symbol
值作为属性的时候, 存取都必须放在方括号内, 否则会出问题. -
Symbol
值作为属性名的时候, 该属性还是公开属性, 比如定义一些常量 -
Symbol
作为属性名, 该属性不会出现在for...in
,for...of
循环中, 也不会被Object.keys()
,Object.getOwnPropertyNames()
返回, 但是, 他也不是一个私有的属性, 有一个Object.getOwnPropertySymbols
方法, 可以获取指定对象的所有Symbol属性名 -
Reflect.ownKeys
方法可以返回所有类型的键名, 包括常规键名和Symbol键名
-
作为属性名的Symbol
-
Symbol
值作为属性的时候, 不会被常规的方法遍历到, 所以为对象定义一些非私有的, 但又😟喜欢只用于内部的方法 -
Symbol.for
为Symbol
值登记的名字, 是全局环境的, 可以在不同的iframe
或者service worker
中取到同一个值
iframe = document.createElement('iframe');
iframe.src = String(window.location);
document.body.appendChild(iframe);
iframe.contentWindow.Symbol.for('foo') === Symbol.for('foo')
由于每一个Symbol
值是不相等的, 这意味着Symbol值可以作为标识符(在编程语言中标识符是用户编程时使用的名字, 对于变量. 常量, 函数, 语句块也有名字, 我们统统称之为标识符), 用于对象的属性名, 就能保证不会出现同名的属性, 这对于一个对象由多个模块构成的情况非常有用, 能防止某一个键被不小心改写或者覆盖..
消除魔术字符串
魔术字符串指的是, 在代码之中多次出现, 与代码形成强耦合的某一个具体的字符串或者数值. 风格良好的代码, 应该尽量消除魔术字符串, 该由语义清晰的变量代替.
- 改变的方式是, 将代码中的字符串, 改变为一个变量
属性名的遍历
Symbol
作为属性名, 该属性不会出现在for...in
,for...of
循环中, 也不会被Object.keys()
,Object.getOwnPropertyNames()
返回. 但是, 它也不是私有属性, 有一个Object.getOwnPropertySymbol
方法, 可以获取指定对象的所有的Symbol属性名
Symbol.for(), Symbol.keyFor()
有时候, 我们希望使用同一个
Symbol
的值,Symbol.for
方法可以做到这一点.它接受一个字符串作为参数, 然后搜索有没有以该参数作为名称的Symbol
值. 如果有, 就返回这个Symbol
值, 否则就新建并返回一个以该字符串为名称的Symbol
值
var s1 = Symbol.for('foo');
var s2 = Symbol.for('foo');
s1 === s2 // true
- Symbol.for() 和 Symbol() 两种写法, 都会生成
Symbol
, 他们的区别是- 前者会被登记到全局环境中提供搜索, 后者不会
-
Symbol.for()
不会每次调用都返回新的Symbol()
值, 而是会先检查给定的key
是否已经存在, 如果不存在才会创建一个值. 比如你调用Symbo.for('dog')
30次, 每次都会返回同一个Symbol
值, 但是调用Symbol('dog')
30次, 会返回30个不同的Symbol
值.
Symbol.keyFor()
返回一个已经登记的
Symbol
类型值得key
var s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
var s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined