ES6-Symbol
概述
Symbol是一种数据类型,代表第一无二的值,Symbol值通过Symbol函数生成,也就是说,对象的属性名现在可以是字符串类型,也可以是Symbol类型.
1 | let s = Symbol() |
Symbol函数前不能使用new命令,否则会报错,这是因为生成的Symbol是一个原始类型的值,不是对象.也就是说,Symbol不是对象,不能添加属性.也可以说Symbol是一种类似于字符串的数据类型.
1 | var s1 = Symbol('foo') |
如果Symbol的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个Symbol对象
1 | var obj = {} |
Symbol函数的参数只表示对该Symbol的描述,因此相同参数的Symbol返回值是不相等的
1 | var s1 = Symbol('a') |
Symbol不能与其他类型的值进行运算,会抛出TypeError
1 | var s1 = Symbol('a') |
但是Symbol可以显式转换成字符串,也可以转换为布尔值
作为属性名的Symbol
由于每一个Symbol值都是不相等的,所以Symbol可以作为标识符用于对象的属性名,保证不会出现同名的属性
1 | var mySymbol = Symbol() |
Symbol作为对象属性名时不能用点运算符
1 | var mySymbol = Symbol() |
因为点运算符后总是字符串,所以不会读取mySymbol作为标识名所指代的值,所以a的属性名是一个字符串,而不是Symbol,同理,在对象内,使用Symbol定义属性时,Symbol必须放在方括号内.
1 | var s = Symbol() |
属性名的遍历
Symbol作为属性名,不会出现在for…in,for…of中,也不会被keys(),getOwnPropertyNames()返回,可以使用getOwnpropertySymbols方法获取指定对象的所有Symbol属性名
1 | var obj = {} |
使用Reflect.ownKeys可以获取到所有的键名,包括字符串和Symbol
1 | var obj = {} |
Symbol不可以用在for循环中.
Symbol.for(),Symbol.keyFor()
有时候希望使用同一个Symbol值,Symbol.for方法可以做到,它接收一个字符串为参数
1 | var s1 = Symbol.for('foo') |
Symbol.keyFor返回一个已登记的Symbol类型的key
1 | var s1 = Symbol.for('foo') |
模块的Singleton模式
Singleton模式是指,调用一个类并且在认识时候都返回同一个实例
我们可以把实例放在顶层对象global中
1 | // mod.js |
1 | var a = require('./mod') |
这样会使加载mod.js时global会失真,为了防止这种情况,我们可以使用Symbol
1 | // mod.js |
1 | module.exports = global[FOO_KEY]var a = require('./mod') |
这样子可以避免global[FOO_KEY]无意间被覆盖,但是还是可以被改写
如果键名也使用Symbol生成,那外部就无法引用到这个值,也就无法被改写
1 | const FOO_KEY = Symbol('foo') |
这样子其他脚本都无法引用FOO_KEY