Symbol
为了保证每个属性的名字都是独一无二的,从根本上防止属性名的冲突,于是在ES6中引入Symbol。
它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
基础属性
不能new
Symbol 值通过Symbol函数生成,不能使用new命令创建,否则会报错,Symbol 值不是对象。
// 创建一个Symbol
let s = Symbol()
typeof s // "symbol"
可添加描述
当Symbol函数接受一个字符串作为参数时,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
如果不加描述的话,输出都为Symbol(),无法区分
// 为Symbol添加描述用以区分
let s1 = Symbol('xixi')
let s2 = Symbol('haha')
s1 //Symbol(xixi)
s2 Symbol(haha)
s1.toString() // 'Symbol(xixi)'
s2.toString() // 'Symbol(haha)'
使用description属性读取所添加的描述
let s1 = Symbol('xixi')
s1.description //'xixi'
相同描述Symbol值不相等
Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
// 没有参数
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
// 有参数
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
对象调用toString方法
// 若Symbol的值是一个对象,就会调用对象的toString方法
let obj = {
toString () {
return '一束黑光'
}
}
let demo = Symbol(obj)
console.log(demo) // Symbol(一束黑光)
不可运算
let blacklight = Symbol('黑光');
"一束" + blacklight
// TypeError: can't convert symbol to string
`一束${blacklight}`
// TypeError: can't convert symbol to string
可转字符串、布尔值,不可转数值
let blacklight = Symbol('黑光');
String(blacklight) // 'Symbol(黑光)'
blacklight.toString() // 'Symbol(黑光)'
Boolean(blacklight) //true
!blacklight // false
Number(blacklight) // TypeError
blacklight + 2 // TypeError
消除魔术字符串
魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。
function getArea (shape, options) {
let area = 0
switch (shape) {
case triangle:
area = .5 * options.width * options.height
break
}
return area
}
getArea(triangle, { width: 100, height: 100 })
上面代码中,字符串Triangle就是一个魔术字符串。它多次出现,与代码形成“强耦合”,不利于将来的修改和维护。
修改方法:将Triangle改为一个变量即可消除强耦合
const shapeType = {
triangle: 'Triangle'
}
function getArea (shape, options) {
let area = 0
switch (shape) {
case shapeType.triangle:
area = .5 * options.width * options.height
break
}
return area
}
getArea(shapeType.triangle, { width: 100, height: 100 })
shapeType.triangle等于哪个值并不重要,只要确保不会跟其他shapeType属性的值冲突即可。因此,这里就很适合改用 Symbol 值
const shapeType = {
triangle: Symbol()
}
扩展方法
Object.getOwnPropertySymbols()
遍历当前对象所有用作属性名的Symbol值。
Symbol作为属性名,不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回
let obj = {}
let a = Symbol('a')
let b = Symbol('b')
obj[a] = 'Hello'
obj[b] = 'World!'
let end = Object.getOwnPropertySymbols(obj)
console.log(end) // [Symbol(a), Symbol(b)]
Symbol.for()
重新使用同一个 Symbol 值
搜索参数名称的Symbol值,如果没有会自动创建,有则使用 🌰
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
Symbol.for("bar") === Symbol.for("bar")
// true
Symbol("bar") === Symbol("bar")
// false
Symbol.keyFor()
返回一个已登记的 Symbol 类型值的
key
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined