javascript对象属性名支持字符串和symbol,字符串键会隐式转换导致覆盖风险,symbol键具唯一性且不被常规遍历和json序列化捕获,访问时需注意语法差异。

JavaScript中对象的属性名可以是字符串或Symbol,两者在遍历、序列化和访问时行为不同,处理时需特别注意。
字符串键名会被自动转为字符串
即使使用数字、布尔等原始值作为属性名,JavaScript也会隐式调用String()转换:
-
obj[42]等价于obj["42"] -
obj[true]等价于obj["true"] -
obj[null]等价于obj["null"] -
obj[undefined]等价于obj["undefined"]
这种隐式转换容易导致意外覆盖(例如obj[0]和obj["0"]指向同一属性),建议显式使用字符串字面量避免歧义。
Symbol键名不会被常规遍历方法捕获
Symbol作为属性名具有唯一性和私有性,for...in、Object.keys()、JSON.stringify()均忽略Symbol键:
-
Object.getOwnPropertyNames(obj):只返回字符串键名 -
Object.getOwnPropertySymbols(obj):专门获取Symbol键名数组 -
Reflect.ownKeys(obj):同时返回字符串键和Symbol键(按创建顺序)
若需完整遍历所有自有属性,应组合使用:[...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)]。
JSON序列化会完全丢弃Symbol键
JSON.stringify()只处理可枚举的字符串键属性,Symbol键及对应值不会出现在结果中:
const obj = { a: 1, [Symbol('b')]: 2 };
JSON.stringify(obj); // '{"a":1}' —— Symbol键'b'彻底消失
如需保留Symbol语义,需手动实现序列化逻辑,例如将Symbol描述(sym.description)作为字符串键暂存,或使用自定义toJSON()方法做映射。
属性访问与存在性检测需区分类型
字符串键可用点号(obj.key)或方括号(obj["key"])访问;Symbol键只能用方括号且必须传入原Symbol值:
obj[sym] === obj[Symbol("desc")] // false,除非是同一个Symbol实例-
obj[sym] = 123;后,sym in obj返回true -
Object.prototype.hasOwnProperty.call(obj, sym)可检测Symbol键是否存在
注意:hasOwnProperty不支持Symbol参数直接调用(obj.hasOwnProperty(sym)会把Symbol转成字符串"Symbol(desc)",结果恒为false)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











