symbol 是 javascript 第七种原始类型,具有唯一性、不可隐式转换、不能用 new 创建;可通过 symbol()、symbol('desc')、symbol.for() 创建,常作对象属性键防冲突,支持内置 symbol 定制行为,但非真正私有且不可作缓存键。

Symbol 是 JavaScript 中第七种原始数据类型,核心特点是“独一无二”,它不参与隐式转换,也不能用 new 创建。创建简单,但用法有讲究,关键在理解它的唯一性和隐藏性。
怎么创建 Symbol
Symbol 只能通过 Symbol() 函数调用生成,不能加 new(否则得到的是对象,不是原始值):
-
基础写法:
const sym = Symbol(); -
带描述符:
const sym = Symbol('user-id');—— 描述仅用于调试和识别,不影响唯一性 -
全局注册表:
const sym = Symbol.for('shared-key');—— 相同字符串会返回同一个 Symbol,适合跨模块共享 -
查全局 key:
Symbol.keyFor(sym)可反向获取已注册 Symbol 的键名(对本地 Symbol 返回undefined)
Symbol 作为对象属性键:防覆盖、避冲突
这是最常见也最实用的场景。用 Symbol 做属性名,能确保不会跟其他代码(包括第三方库或后续扩展)的字符串键名撞车:
- 必须用方括号访问:
obj[sym] = 'private data';,obj.sym无效 - 常规遍历不可见:
for...in、Object.keys()、JSON.stringify()都忽略 Symbol 键 - 但仍可被获取:
Object.getOwnPropertySymbols(obj)或Reflect.ownKeys(obj)能拿到它们
内置 Symbol:定制对象行为
ES6 预定义了一批以 Symbol. 开头的特殊值,用于自定义对象在特定场景下的表现:
-
Symbol.iterator:让对象支持for...of循环,返回迭代器对象 -
Symbol.toPrimitive:控制对象转原始值时的行为(比如+obj或String(obj)) -
Symbol.hasInstance:重写instanceof的判断逻辑 -
Symbol.toStringTag:影响Object.prototype.toString.call(obj)的输出内容 -
Symbol.asyncIterator:支持for await...of异步遍历
注意限制与常见误区
Symbol 看似灵活,但有几条硬边界必须清楚:
-
不能隐式转换:拼接字符串(
'id: ' + sym)、转数字(Number(sym))都会报错 -
可显式转字符串:
sym.toString()或String(sym)可用,结果形如"Symbol(user-id)" -
不能当缓存键:
localStorage.setItem(sym, 'val')会失败,因为底层要求键为字符串 -
非真正私有:虽然常规方式访问不到,但通过
getOwnPropertySymbols仍可枚举,不适合做安全隔离











