对象字面量{}最安全,避免new遗漏和原型污染;属性名含空格需引号;方法是函数值,支持简写;计算属性用[key];点号访问合法标识符,方括号支持动态键;this绑定取决于调用方式;Object.defineProperty默认不可枚举。
直接用 {} 创建对象,适合一次性定义结构明确的数据。它天然避免了构造函数调用时忘记 new 的问题,也不涉及原型链污染风险。
常见错误是误把逗号写在最后一项后面(虽然现代引擎大多容忍,但 IE8 及更早版本会报 Unexp);还有人试图在字面量里写方法体带
ected token }return 语句却忘了加函数关键字。
{"user name": "Alice"}
sayHi: function() { return "Hi"; } 或简写为 sayHi() { return "Hi"; }
[keyName]: "value",其中 keyName 是变量. 只能访问合法标识符命名的属性,写法简洁;[] 支持动态键名、数字索引、保留字甚至表达式,但性能略低且易因类型转换出错(比如 obj[1] 实际查的是 "1" 这个字符串键)。
典型翻车现场:把 obj.user.name 写成 obj["user.name"] —— 后者查的是名为 "user.name" 的单一属性,不是嵌套路径。
obj.name、obj.sayHi()
obj["first name"]、obj[variableKey]、obj[123]
undefined,不会报错;但对 undefined 调用方法会抛 TypeError
this 指向取决于调用方式,不是定义位置这是最容易被忽略的复杂点。同一个函数赋给不同对象,this 就不同;从对象上取出来单独调用,this 会丢失(非严格模式下指向全局,严格模式下为 undefined)。
例如:
const obj = {
name: "Bob",
greet() { console.log("Hello, " + this.name); }
};
const fn = obj.greet;
fn(); // 输出 "Hello, undefined"(严格模式)或报错
this 绑定可用 bind、箭头函数(但箭头函数不能作为构造函数)、或调用时用 call/apply
constructor 里手动 bind 或改用箭头函数this.xxx,不能省略 this
for...in 和 JSON.stringify
用 Object.defineProperty 添加的属性默认不可枚举(enumerable: false),这意味着它不会出现在 for...in 循环里,也不会被 JSON.stringify 序列化——这点常被忽略,导致调试时“看不见”某些属性。
例如:
const obj = {};
Object.defineProperty(obj, "secret", {
value: "hidden",
enumerable: false
});
console.log(JSON.stringify(obj)); // "{}"
enumerable: true
Object.keys() 只返回可枚举自有属性,Object.getOwnPropertyNames() 才包含不可枚举的class 或私有字段 #field 控制可见性,而非依赖 enumerable
this 是否按预期绑定、以及属性是否可枚举——这四点覆盖了 90% 的实际坑。写的时候多看一眼控制台输出的完整对象结构,比背规则管用。