Symbol 通过 Symbol() 函数创建,天然唯一且不可隐式转换;支持带描述创建(仅调试用)、禁止 new 调用;可用作对象隐藏属性键(需方括号访问);跨模块共享需用 Symbol.for() 和 Symbol.keyFor();内置 Symbol.iterator 等可定制对象行为。

直接调用 Symbol() 函数就能创建一个 Symbol 值,它天然唯一、不可重复,也不参与类型隐式转换——这是它作为“唯一标识”的根基。
怎么创建 Symbol
Symbol 没有字面量写法,必须通过函数调用生成:
-
基础创建:
const sym = Symbol();—— 每次调用都返回全新值,Symbol() === Symbol()永远为false -
带描述的创建:
const uid = Symbol('user id');—— 描述仅用于调试输出(如console.log(uid)显示Symbol(user id)),不影响值本身,相同描述也绝不相等 -
禁止 new:
new Symbol()会抛出TypeError,因为 Symbol 是原始类型,不是构造函数
怎么用作对象属性键
Symbol 最常见的用途是当对象的“防冲突属性名”,避免被覆盖或意外遍历:
- 必须用方括号语法赋值和读取:
obj[sym] = 'private data';,不能用点号(obj.sym无效) - 该属性不会出现在
for...in、Object.keys()、JSON.stringify()中,具有“隐藏性” - 但不是真正私有:可通过
Object.getOwnPropertySymbols(obj)获取所有 Symbol 键,再配合反射访问
怎么跨模块共享同一个 Symbol
如果需要多个文件/模块共用一个 Symbol(比如统一的调试标识),用全局注册表:
立即学习“Java免费学习笔记(深入)”;
-
Symbol.for('debug'):先查全局池,存在则复用,否则新建并登记;多次调用同名返回同一值 -
Symbol.keyFor(sym):仅对Symbol.for()创建的 Symbol 有效,可反查注册时用的字符串键名 - 注意区分:
Symbol('debug')和Symbol.for('debug')完全不同,前者永远唯一,后者可共享
怎么定制对象行为(内置 Symbol)
JavaScript 预定义了一批以 Symbol.xxx 形式存在的“知名 Symbol”,用于接管对象的底层行为:
-
[Symbol.iterator]():让对象支持for...of和展开运算符(如数组、Set 的遍历逻辑就靠它) -
[Symbol.toStringTag]:控制Object.prototype.toString.call(obj)的返回结果(如设为"Person",输出变成[object Person]) -
[Symbol.toJSON]():自定义该对象在JSON.stringify()中的序列化表现


















