Symbol 是什么,有什么作用?
面试速答(30 秒版 TL;DR)
Symbol是一种原始类型(primitive),每个Symbol()值都“保证唯一”。- 主要用途是做对象的唯一属性键,避免命名冲突(尤其是库代码、框架扩展点)。
- 还有一类“内置/知名 Symbol(well-known symbols)”用于定制语言行为,例如
Symbol.iterator让对象可迭代。
为什么需要 Symbol?
对象属性名传统上只有字符串,这会带来两个问题:
- 不同模块/库可能用同一个字符串 key,容易冲突覆盖。
- 想做“内部私有标记”时,字符串 key 很容易被误用或被枚举出来。
Symbol 作为 key 的价值:几乎不可能“撞名”,更适合做扩展点或内部标记。
最小例子:用 Symbol 做“不会冲突的 key”
const internalId = Symbol('internalId');
const user = {
name: 'Alice',
[internalId]: 42,
};
console.log(user[internalId]); // 42
console.log(Object.keys(user)); // ["name"],Symbol key 不会出现在这里
console.log(Object.getOwnPropertySymbols(user)); // [Symbol(internalId)]
要点:Symbol 属性默认不会被 Object.keys / for...in 枚举到,但它并不是“安全私有”,只是降低误用。
重点:Symbol.iterator 与可迭代协议
当对象实现了 obj[Symbol.iterator]() 并返回一个 iterator,它就能被 for...of、展开运算符 ...、Array.from 等消费。
const iterable = {
data: [1, 2, 3],
[Symbol.iterator]() {
let i = 0;
return {
next: () => {
if (i >= this.data.length) return {done: true, value: undefined};
return {done: false, value: this.data[i++]};
},
};
},
};
console.log([...iterable]); // [1, 2, 3]
常见追问
Symbol.for(key):从全局注册表取同一个 symbol(跨文件/模块共享)。Symbol(key)则总是创建新值。JSON.stringify:会忽略 Symbol 值与 Symbol key(常见踩坑点)。
易错点/坑
- 把 Symbol 当成“真正私有”:它只是不可轻易枚举,但仍可通过
getOwnPropertySymbols取到。 - 把
Symbol.for和Symbol()混淆:一个“全局复用”,一个“永远唯一”。
速记要点(可背诵)
- Symbol:唯一的 primitive,常用来做“不会冲突的对象属性 key”。
- well-known symbols:用来定制语言行为,
Symbol.iterator最常考。