js基础:Symbol 的作用

symboooool

Symbol 是什么

symbol 是一种基本数据类型,Symbol() 函数是一个静态方法,会返回一个 symbol 类型的值,但它不是一个构造函数。

Symbol 的作用

在 js 代码中,对象的属性 key 必须是字符串,当使用引用类型作为 key 时,会调用 Symbol.toPrimitive / toString 转换成一个字符串。如:

1
2
3
4
5
const a = {}
console.log({
[a]: 1,
})
// 输出 {[object Object]: 1}

Symbol 的一个主要作用就是作为对象的 key => 这可不是我瞎说的,原话:

一个 symbol 值能作为对象属性的标识符;这是该数据类型仅有的目的。

Symbol 作为 key 有什么优势呢

  1. 因为 Symbol 生成的值是唯一的,所以可以保证 key 不冲突。当我们在写一个工具方法、库的时候,例如要在 window 上挂载一个全局变量,可能存在命名的冲突(虽然可能性也不大)。如果用 Symbol 就可以避免。
1
2
3
4
5
6
7
const key1 = Symbol('my-util') // 参数仅仅作为标识作用
const key2 = Symbol('my-util')

window[key1] = function () {}
window[key2] = function () {}

key1 === key2 // false
  1. 但是 uuid 不也可以实现吗?可以是可以,但 Symbol 类型的 key 值还有一个特性,就是它会在遍历时/序列化时被隐藏,可以模仿私有属性,如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const key = Symbol('private')
const obj = {
[key]: 1,
num: 2,
}
// 遍历
for (let key in obj) {
console.log(key) // num
}
// 取出key
Object.getOwnPropertyNames(obj) // ['num']
// 取出key
Object.keys(obj) // ['num']
// 序列化
JSON.stringify(obj) // '{"num":2}'
  1. 虽然如此,但是 uuid 也可以实现类似的效果,只要关掉可枚举即可
1
2
3
4
5
6
Object.defineProperty(obj, 'num', {
value: 2,
enumerable: false,
})
// 取出key
Object.keys(obj) // ['num']
  1. 而且强行要访问 symbol 类型的 key 也是可以的:
1
2
3
4
Object.getOwnPropertySymbols(obj) // [Symbol(private)]
// 取
const keySymbol = Object.getOwnPropertySymbols(obj)[0]
console.log(obj[keySymbol]) // 1

所以要模拟也不是不行,但是 Symbol 更简便,为什么不用呢。

综上:Symbol 的作用在于生成唯一的值,并且作为一种弱形式的信息隐藏,主要作用是作为对象属性的标识符。