登录
以往,js 的数据类型有 Number、String、Boolean、Object、null 和 undefined。
ES6 则引入了一种新的原始数据类型:Symbol,表示独一无二的值。
Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象。可以接受一个字符串作为参数,为新创建的 Symbol 提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分。
// 使用同一参数创建的 Symbol,生成的值也是不同的
let sym_1 = Symbol('sym')
let sym_2 = Symbol('sym')
console.log(sym_1 === sym_2) // false
console.log(sym_1 === sym_1) // true
console.log(sym_1) // Symbol(sym)
console.log(typeof(sym_1)) // symbol
Symbol 最大的用途是用作对象的唯一属性值,且这个属性是无法遍历的。
// 使用同一字符串创建的三个 Symbol,可以用作对象的三个key
let key_1 = Symbol('key')
let key_2 = Symbol('key')
let key_3 = Symbol('key')
let obj = {
a: 1,
b: 2,
[key_1]: 10,
[key_2]: undefined,
}
// 修改已有的值
obj[key_2] = 200
// 在对象外部赋值
obj[key_3] = 300
// 拥有 key 的前提下,不影响使用
console.log(obj[key_1]) // 10
console.log(obj[key_2]) // 200
console.log(obj[key_3]) // 300
// 无法遍历,无法用其他方式获取 key
console.log(JSON.stringify(obj)) // {"a":1,"b":2}
console.log(Object.keys(obj)) // ["a", "b"]
单单查看,无法分清三个 key,如果要读取到一个对象的 Symbol 属性,需要用以下两个方法:
console.log(Reflect.ownKeys(obj)) // ["a", "b", Symbol(key), Symbol(key), Symbol(key)]
console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(key), Symbol(key), Symbol(key)]
console.log(Object.getOwnPropertySymbols(obj)[0] === key_1) // trye
Symbol.for(str):类似单例模式,首先会在全局搜索,是否有基于字符串 str 为创建的 Symbol,如果有即返回该 Symbol,若没有则新建该 Symbol 并返回,同时登记在全局环境中,以供之后的搜索。
Symbol.keyFor(Symbol):传入一个 Symbol,再全局搜索该 Symbol 是否已登记,已登记的话就返回创建它所基于的那个字符串,否则返回 undefined。
let sym_not_1 = Symbol('key') // 普通声明
let sym_1 = Symbol.for('key') // 使用 Symbol.for 登记
let sym_2 = Symbol.for('key') // 再次使用 Symbol.for
console.log(Symbol.keyFor(sym_not_1)) // undefined - 因为此 Symbol 没有登记
console.log(Symbol.keyFor(sym_1)) // key - 获取到此 Symbol 的字符串
console.log(sym_1 === sym_2) // true - 类似单例模式,所以两个是相等的
console.log(sym_1 === sym_not_1) // false - 两个毫不相关