Symbol 是 JavaScript 中唯一能创建真正唯一、不可枚举、不冲突的属性键的原始类型;它专为标识符设计,用于定义对象私有或内部属性以避免命名碰撞,支持唯一键生成、隐藏属性、全局共享(Symbol.for)及标准协议实现。

Symbol 是 JavaScript 中唯一能创建真正唯一、不可枚举、不冲突的属性键的原始类型。它不用于表示值,而是专为“标识符”而生——尤其适合定义对象中私有或内部属性,避免命名碰撞。
用 Symbol 创建唯一属性键
每次调用 Symbol() 都返回一个全新且不相等的值,即使描述相同:
const key1 = Symbol('id');
const key2 = Symbol('id');
console.log(key1 === key2); // false
console.log(key1.toString()); // "Symbol(id)"
这个特性天然保证了属性名的唯一性——不同模块、不同开发者创建的同名 Symbol 也不会覆盖彼此。
作为对象属性名隐藏内部字段
Symbol 作属性名时,该属性不会出现在 for...in、Object.keys()、JSON.stringify() 中,也不被 Object.assign() 拷贝(除非显式处理):
立即学习“Java免费学习笔记(深入)”;
- 用
Object.getOwnPropertySymbols()可获取所有 Symbol 键 - 用
Reflect.ownKeys()可同时拿到字符串键和 Symbol 键 - 属性仍可被读写,只是“隐身”于常规遍历逻辑之外
使用 Symbol.for() 实现全局共享 Symbol
若需跨模块复用同一 Symbol(如统一定义某个内部状态标识),可用 Symbol.for(key):
const shared = Symbol.for('debugMode');
const same = Symbol.for('debugMode');
console.log(shared === same); // true
它会检查全局注册表,存在则复用,不存在则新建并登记。注意:这牺牲了“绝对唯一”,换来了跨上下文一致性。
常见用途示例
- 定义类的私有方法/状态:用 Symbol 作方法名,防止子类意外重写
- 实现迭代器协议:
[Symbol.iterator]是标准约定,引擎据此识别可迭代对象 - 自定义行为钩子:
Symbol.toPrimitive控制对象转原始值逻辑 - 库作者避免污染用户对象:给内部缓存加 Symbol 键,不干扰用户自有属性











