Symbol 是 JavaScript 中唯一绝对不重复的原始类型,用于避免对象属性命名冲突、隐藏内部状态,并通过 Symbol.for() 实现跨模块共享及内置 Symbol 定制对象行为。

Symbol 是 JavaScript 中唯一能保证“绝对不重复”的原始类型,它的核心用途就是当你要往对象里加一个键,又怕跟别人撞上时,用它最稳妥。
Symbol 作为对象属性名,天然避免命名冲突
字符串属性名是靠名字匹配的,两个模块都写 obj.id = 123,后写的就会覆盖前写的。而 Symbol 每次调用 Symbol() 都生成一个全新值,哪怕描述一样,也不相等:
-
Symbol('id') === Symbol('id')→ false - 所以
user[Symbol('id')] = 1和user[Symbol('id')] = 2实际操作的是两个完全不同的属性 - 不同模块各自定义自己的 Symbol,互不影响,不会覆盖也不会误读
Symbol 属性默认不可枚举,适合放内部状态
用 Symbol 当键添加的属性,不会出现在以下遍历中:
-
for...in循环 Object.keys()JSON.stringify()
这意味着你可以把元数据、缓存、内部计数器之类的东西挂上去,外部代码“看不见”,也不会被意外序列化或遍历到。当然,它不是真正私有——Object.getOwnPropertySymbols() 还是能拿到,但至少做到了“默认隐身”。
立即学习“Java免费学习笔记(深入)”;
Symbol.for() 支持跨模块共享唯一键
如果确实需要多个地方访问同一个 Symbol(比如统一的调试标识或全局配置键),可以用 Symbol.for(key):
-
Symbol.for('debug')第一次调用会创建,之后再调用返回同一个值 -
Symbol.for('debug') === Symbol.for('debug')→ true - 这相当于在全局注册表里存了一个带名字的 Symbol,适合框架级约定
内置 Symbol 让对象行为可定制
JavaScript 预留了一批以 Symbol. 开头的“知名 Symbol”,用来挂钩语言底层行为:
-
[Symbol.iterator]:让对象支持for...of和展开运算符 -
[Symbol.toStringTag]:控制Object.prototype.toString.call(obj)的输出内容 -
[Symbol.toPrimitive]:定义对象参与加减、比较等运算时怎么转成原始值
这些不是随便起的名字,而是引擎识别的“协议入口”,填进去就能改对象的表现逻辑,属于元编程的关键手段。











