Symbol 是 JavaScript 中唯一全局唯一的原始值,用于定义不可枚举、避免命名冲突的对象属性键;需用方括号语法定义,不被 Object.keys() 等遍历,可用 Object.getOwnPropertySymbols() 获取,Symbol.for() 支持全局复用。

Symbol 类型在 JavaScript 中是唯一能保证“全局唯一”的原始值,常被用于定义对象中不希望被意外覆盖或枚举的属性键名。它和对象字面量的键名定义结合使用时,既可避免命名冲突,又能实现私有属性的效果(尽管不是真正私有)。
Symbol 作为对象字面量的键名
Symbol 可以直接用作对象字面量中的属性名,但必须用方括号语法包裹,否则会被当作字符串处理:
-
错误写法:
{ mySym: 'value' }—— 这里mySym是字符串键,不是 Symbol -
正确写法:
{ [mySym]: 'value' }—— 使用计算属性名语法才能插入 Symbol 键
例如:
const sym = Symbol('id');
const obj = {
[sym]: 123,
name: 'Alice'
};
console.log(obj[sym]); // 123
console.log(Object.keys(obj)); // ['name'] —— Symbol 键不会出现在 keys 中
Symbol 键不会被常规遍历方式访问
Symbol 定义的属性键具有“不可枚举”特性(enumerable: false),因此不会被 for...in、Object.keys()、JSON.stringify() 等默认遍历方式捕获:
立即学习“Java免费学习笔记(深入)”;
-
Object.getOwnPropertyNames(obj)也不包含 Symbol 键(它只返回字符串键) - 要用
Object.getOwnPropertySymbols(obj)显式获取所有 Symbol 键 -
Reflect.ownKeys(obj)同时返回字符串键和 Symbol 键
Symbol.for() 与全局注册表
普通 Symbol() 每次调用都生成新值,而 Symbol.for(key) 会先检查全局符号注册表,存在则复用,适合跨模块共享键名:
-
Symbol.for('debug') === Symbol.for('debug')→ true -
Symbol('debug') === Symbol('debug')→ false
注意:Symbol.keyFor(sym) 只对 Symbol.for() 创建的 Symbol 有效,返回注册时用的字符串键。
实际使用建议
Symbol 不是“私有属性”的终极方案(仍可通过 getOwnPropertySymbols 访问),但它适合以下场景:
- 为库添加内部方法或元数据,避免用户代码意外覆盖
- 定义协议性键名,如
Symbol.iterator、Symbol.toStringTag - 在类中模拟弱私有字段(配合 WeakMap 更稳妥)
不推荐用 Symbol 替代真正的访问控制逻辑,也不宜过度依赖其“隐蔽性”。它的价值在于语义清晰与冲突规避,而非安全封装。


















