Symbol 是 JavaScript 中唯一能作为对象属性键且不被常规遍历捕获的原始类型,因其不可枚举性可实现“隐藏属性”;但非真正私有,仅规避意外访问与枚举暴露。

Symbol 是 JavaScript 中唯一能作为对象属性键、又不被常规遍历捕获的原始类型,天然适合实现“隐藏属性”——不是真正私有,但能规避意外访问和枚举暴露。
为什么 Symbol 能隐藏属性
Symbol 属性默认具有不可枚举性(non-enumerable):
- 不会出现在 for...in 循环中
- 不会被 Object.keys()、Object.getOwnPropertyNames() 返回
- 不会被 JSON.stringify() 序列化
- 不会出现在 console.log(obj) 的默认展开视图里(部分浏览器会显示,但不参与遍历逻辑)
如何正确添加和访问 Symbol 属性
必须用同一个 Symbol 值作为键才能读写,不能靠描述字符串动态生成:
- ❌ 错误:每次
Symbol('id')都是新值,无法复用 - ✅ 正确:先创建 Symbol 变量,再统一用它做键
示例:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
const secretId = Symbol('user-id');
const user = {
name: 'Alice',
[secretId]: 'usr_8a2f'
};
console.log(user[secretId]); // 'usr_8a2f' —— 可正常访问
console.log(Object.keys(user)); // ['name'] —— Symbol 属性不出现
console.log(JSON.stringify(user)); // {"name":"Alice"} —— 不序列化
如何发现和操作已有的 Symbol 属性
虽然隐藏,但并非不可见。需使用专用 API:
- Object.getOwnPropertySymbols(obj):只返回对象自身的 Symbol 键数组
- Reflect.ownKeys(obj):返回所有键(含字符串 + Symbol)
- obj.hasOwnProperty(sym) 或 sym in obj:可检测是否存在该 Symbol 属性
例如:
const sym = Symbol('meta');
user[sym] = { createdAt: Date.now() };
console.log(Object.getOwnPropertySymbols(user)); // [Symbol(meta)]
console.log(Reflect.ownKeys(user)); // ['name', Symbol(meta)]
注意边界:这不是真正的私有
Symbol 隐藏的是“遍历可见性”,不是访问权限:
- 只要拿到 Symbol 实例(比如通过模块导出、全局注册或调试时获取),就能自由读写
- 无法阻止 for...of 或 Object.assign 等操作间接暴露(除非配合 Object.defineProperty 设置
enumerable: false,但 Symbol 默认已是 false) - 若需更强封装,应结合闭包或 #privateField(ES2022 私有字段)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










