对象属性名用字符串或symbol时访问方式不可混用:字符串键可用点号或方括号(含特殊字符时仅方括号),数字等会转字符串;symbol键只能用方括号且需原值,不参与遍历与json序列化,全局symbol通过symbol.for()共享。

对象属性名用字符串还是 Symbol,访问方式不能混用——这是 JavaScript 的硬性规则,不是风格偏好。
字符串键:点号和方括号都行
只要属性名是合法标识符(比如 name、user_id),就能用点号直接访问:obj.name;也支持方括号:obj["name"]。两者语义等价,现代引擎下性能没差别。
- 含特殊字符的字符串键(如
"full-name"、"1st-login")只能用方括号,点号会报语法错误 - 数字、布尔、null 等作为键时会被自动转成字符串,
obj[42]和obj["42"]访问的是同一个属性 - 避免隐式转换带来的覆盖风险,比如
obj[0]和obj["0"]冲突,建议统一用字符串字面量
Symbol 键:只能用方括号,且必须用原值
Symbol 是唯一值,哪怕描述相同,Symbol("id") !== Symbol("id")。所以访问时不能靠“名字”猜,必须持有创建时的那个 Symbol 实例。
-
obj[sym]可以读写,但obj.sym永远是undefined(点号只认字符串) -
sym in obj能正确判断 Symbol 键是否存在;而obj.hasOwnProperty(sym)会把 Symbol 转成字符串再查,结果恒为false - 要用
Object.prototype.hasOwnProperty.call(obj, sym)或Reflect.has(obj, sym)才可靠
遍历与序列化:Symbol 键默认“隐身”
Symbol 键不会出现在常规遍历中,也不是 JSON 的一部分,这既是限制,也是设计意图——用于内部状态、元信息或私有字段。
-
for...in、Object.keys()、JSON.stringify()全部忽略 Symbol 键 - 想拿到所有键(含 Symbol),用
Reflect.ownKeys(obj) - 只想提取 Symbol 键,用
Object.getOwnPropertySymbols(obj) - 需要序列化 Symbol 数据时,得手动映射,比如把
sym.description当作临时字符串键保存
全局 Symbol:跨模块复用同一键
普通 Symbol("id") 每次都新建,互不相等;而 Symbol.for("id") 会查全局注册表,同名返回同一个实例。
-
Symbol.for("debug") === Symbol.for("debug")返回true - 可用
Symbol.keyFor(sym)反查注册名,仅对Symbol.for()创建的 Symbol 有效 - 适合插件系统、框架扩展等需要约定键名但又不想硬编码字符串的场景











