对象字面量{}最常用安全,适合结构明确场景;Object.defineProperty用于精确控制单个属性;点号访问要求合法标识符,方括号支持动态键名;深层嵌套推荐可选链+空值合并。
直接用 {} 创建对象,适合结构明确、属性固定且数量不多的场景。浏览器和 Node.js 都完全支持,无兼容性问题。
常见错误是误把逗号写在最后一项后面(尤其在旧版 IE 中会报错),虽然现代引擎大多容忍,但建议保持严谨:
const user = {
name: 'Alice',
age: 30,
isActive: true
};
name、age、isActive 是属性名,冒号后是对应值{"full name": "Alice"}
undefined
Object.defineProperty 精确控制属性行为当需要定义不可枚举、不可修改或带 getter/setter 的属性时,Object.defineProperty 是唯一可靠选择。它不适用于批量初始化,而是用于增强已有对象的特定字段。
典型误用是试图用它“批量添加多个属性”——每次只能定义一个,循环调用效率低且易出错。
const obj = {};
Object.defineProperty(obj, 'count', {
value: 0,
writable: false, // 不能被重新赋值
enumerable: false, // for...in 不会遍历到
configurable: false // 不能再用 defineProperty 修改该属性
});
writable: false 和 configurable: false 一旦设为 false,就无法再改回 true
get/set 函数,而不是在 value 中放函数obj.prop 和 obj["prop"] 表面等价,但行为差异很大。点号要求属性名是合法标识符且已知;方括号支持动态键名、保留字、空格等,但性能略低。
常见陷阱是把变量当字面量用:obj.keyName 总是读 keyName 这个字面属性,不是变量 keyName 的值。
const keyName = 'age'; console.log(user.keyName); // undefined(不是 30) console.log(user[keyName]); // 30(正确)
user-data)、数字开头(如 1stPlace)或为保留字(如 class)时,只能用方括号obj?.prop(可选链)能避免 Cannot read property 'x' of undefined 错误,但只适用于点号访问obj[foo()] 会先调用 foo()
像 user.profile.address.city 这种多层访问,任何中间环节为 null 或 undefined 就会抛错。靠 try/catch 太重,也不利于调试。
现代写法首选可选链 + 空值合并: user?.profile?.a。如果环境不支持(如 IE 或旧版 Node),需手动检查或用工具函数。
if (user && user.profile && user.profile.address) —— 冗长且易漏层级get(user, 'profile.address.city', 'Unknown') 是兼容方案,但引入依赖要权衡const { city = 'Unknown' } = user?.profile?.address || {};
defineProperty,动态访问用方括号,深层嵌套必加可选链——这些不是风格偏好,而是运行时是否崩掉的分界线。