Symbol 的语法
Symbol不是一个对象,也没有构造函数,因此无法使用new创建。
可以理解为不可重复的字符串
两个看上去相同的Symbol会返回false
let a = Symbol()
let b = Symbol()
console.log(a === b) // false
let a = Symbol('Faker')
let b = Symbol('Faker')
console.log(a === b) // false
使用toString()方法会返回symbol值的字符串形式
let a = Symbol('Faker')
console.log(a.toString()) // Symbol(Faker)
对于对象,可以通过改写toString来实现一些业务逻辑
let obj = {
name: 'Faker',
toString() {
return this.name
}
}
let a = Symbol(obj)
console.log(a.toString()) // Symbol(Faker)
description
一个API,用于返回描述。一个字符串
let a = Symbol('Faker')
console.log(a.description) // Faker
不同的定义方法
使用普通的定义方法时,会将Symbol独立生成
let a = Symbol('Faker')
let b = Symbol('Faker')
console.log(a === b) // false
使用for定义时,会在全局环境中注册,如果内容相同,则多个Symbol会指向相同的数据地址。
let a = Symbol.for('Faker')
let b = Symbol.for('Faker')
console.log(a === b) // true
可以使用静态方法keyFor()查询注册在全局变量中的Symbol
let a = Symbol.for('Faker')
console.log(Symbol.keyFor(a)) // Faker
Symbol的用途
区分同名属性
独一无二:将Symbol作为属性的key,保证同名属性之间并不冲突。
如果一个类中有两个同名属性,使用一般方法则不能保证互相区分开。
如下,两个都叫Faker的队员只会输出一个Faker
let SKT = {
Faker: { name: 'Faker', age: 24, play: 'Mid' },
Faker: { name: 'Faker', age: 24, play: 'Bot' }
}
console.log(SKT) // {Faker: {…}}
如果使用Symbol作为属性的Key,则可以很好地将同名属性分开。
let mid = Symbol('Faker')
let bot = Symbol('Faker')
let SKT = {
[mid]: { name: 'Faker', age: 24, play: 'Mid' },
[bot]: { name: 'Faker', age: 24, play: 'Bot' }
}
console.log(SKT) // {Symbol(Faker): {…}, Symbol(Faker): {…}}
console.log(SKT[mid]) // {name: "Faker", age: 24, play: "Mid"}
console.log(SKT[bot]) // {name: "Faker", age: 24, play: "Bot"}
隐藏属性
类似于私有属性,封装
一般的对象遍历方式无法遍历以Symbol作为Key的属性。
这里列出了不同遍历方式对于遍历到属性形式的影响。
let mid = Symbol('Faker')
let SKT = {
[mid]: { name: 'Faker', age: 24, play: 'Mid' },
Bang: { name: 'Bang', age: 24, play: 'Bot' }
}
// 普通遍历 只能遍历普通属性
for (let a in SKT) {
console.log(a, SKT[a]) // Bang {name: "Bang", age: 24, play: "Bot"}
}
// Object.keys() 只能遍历普通属性
for (let key of Object.keys(SKT)) {
console.log(key, SKT[key])
// Bang {name: "Bang", age: 24, play: "Bot"}
}
// Object.getOwnPropertyNames() 指定遍历普通属性
for (let key of Object.getOwnPropertyNames(SKT)) {
console.log(key, SKT[key])
// Bang {name: "Bang", age: 24, play: "Bot"}
}
// Object.getOwnPropertySymbols() 指定遍历Symbol作为Key的属性
for (let key of Object.getOwnPropertySymbols(SKT)) {
console.log(key, SKT[key])
// Symbol(Faker) {name: "Faker", age: 24, play: "Mid"}
}
// 所有属性形式均可遍历
for (let key of Reflect.ownKeys(SKT)) {
console.log(key, SKT[key])
// Bang {name: "Bang", age: 24, play: "Bot"}
// Symbol(Faker) {name: "Faker", age: 24, play: "Mid"}
}
消除魔法字符串
魔法字符串:指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或数值。风格良好的代码,应该尽量消除魔法字符串,而由含义清晰的变量代替。
由于Symbol独一无二的特性,可以很好地代替魔法字符串。