物件初始化器
物件初始化器是一個由零個或多個屬性名及其關聯值的對組成的、用逗號分隔的列表,用花括號 ({}) 括起來。物件也可以使用 Object.create() 或 透過使用 new 運算子呼叫建構函式 來初始化。
試一試
const object1 = { a: "foo", b: 42, c: {} };
console.log(object1.a);
// Expected output: "foo"
const a = "foo";
const b = 42;
const c = {};
const object2 = { a: a, b: b, c: c };
console.log(object2.b);
// Expected output: 42
const object3 = { a, b, c };
console.log(object3.a);
// Expected output: "foo"
語法
o = {
a: "foo",
b: 42,
c: {},
1: "number literal property",
"foo:bar": "string literal property",
shorthandProperty,
method(parameters) {
// …
},
get property() {},
set property(value) {},
[expression]: "computed property",
__proto__: prototype,
...spreadProperty,
};
描述
物件初始化器是描述 Object 初始化的表示式。物件由用於描述物件的“屬性”組成。物件屬性的值可以包含原始資料型別或其他物件。
物件字面量語法 vs. JSON
物件字面量語法與 JavaScript Object Notation (JSON) 不同。儘管它們看起來相似,但它們之間存在差異。
- JSON“只”允許使用
"property": value語法定義屬性。屬性名必須用雙引號括起來,並且定義不能是簡寫形式。也不允許使用計算屬性名。 - JSON 物件屬性值只能是字串、數字、
true、false、null、陣列或另一個 JSON 物件。這意味著 JSON 不能表示方法或非普通物件,例如Map或RegExp。 - 在 JSON 中,
"__proto__"是一個普通的屬性鍵。在物件字面量中,它設定了物件的原型。
JSON 是物件字面量語法的“嚴格子集”,這意味著每個有效的 JSON 文字都可以被解析為物件字面量,並且很可能不會導致語法錯誤。唯一的例外是物件字面量語法禁止重複的 __proto__ 鍵,這不適用於 JSON.parse()。後者將 __proto__ 視為普通屬性,並取最後一次出現的作為屬性值。它們所代表的物件值(即它們的語義)唯一不同的時候是源包含 __proto__ 鍵的時候——對於物件字面量,它設定物件的原型;對於 JSON,它是一個普通屬性。
console.log(JSON.parse('{ "__proto__": 0, "__proto__": 1 }')); // {__proto__: 1}
console.log({ "__proto__": 0, "__proto__": 1 }); // SyntaxError: Duplicate __proto__ fields are not allowed in object literals
console.log(JSON.parse('{ "__proto__": {} }')); // { __proto__: {} }
console.log({ "__proto__": {} }); // {} (with {} as prototype)
示例
建立物件
可以像這樣建立一個沒有屬性的空物件
const object = {};
然而,字面量或初始化器表示法的優點是,你可以在花括號內快速建立帶有屬性的物件。你用逗號分隔的 key: value 對列表表示。
以下程式碼建立了一個具有三個屬性的物件,鍵分別為 "foo"、"age" 和 "baz"。這些鍵的值分別為字串 "bar"、數字 42 和另一個物件。
const object = {
foo: "bar",
age: 42,
baz: { myProp: 12 },
};
訪問屬性
一旦建立了物件,你可能想要讀取或更改它們。可以使用點表示法或方括號表示法來訪問物件屬性。(有關詳細資訊,請參閱屬性訪問器。)
object.foo; // "bar"
object["age"]; // 42
object.baz; // {myProp: 12}
object.baz.myProp; // 12
屬性定義
我們已經學習瞭如何使用初始化器語法來表示屬性。通常,你的程式碼中有一些變數,你希望將它們放入物件中。你會看到這樣的程式碼
const a = "foo";
const b = 42;
const c = {};
const o = {
a: a,
b: b,
c: c,
};
有一種更短的表示法可以實現相同的目的
const a = "foo";
const b = 42;
const c = {};
// Shorthand property names
const o = { a, b, c };
// In other words,
console.log(o.a === { a }.a); // true
重複的屬性名
當對屬性使用相同的名稱時,第二個屬性將覆蓋第一個屬性。
const a = { x: 1, x: 2 };
console.log(a); // {x: 2}
ES2015 之後,在任何地方都允許重複的屬性名,包括嚴格模式。你也可以在類中擁有重複的屬性名。唯一的例外是私有元素,它們在類體中必須是唯一的。
方法定義
const o = {
property: function (parameters) {},
get property() {
return 1;
},
set property(value) {},
};
可以使用簡寫符號,這樣就不再需要 function 關鍵字。
// Shorthand method names
const o = {
property(parameters) {},
};
還有一種簡潔地定義生成器方法的方法。
const o = {
*generator() {
// …
},
};
這等同於這種類似 ES5 的表示法(但請注意 ECMAScript 5 沒有生成器)
const o = {
generator: function* () {
// …
},
};
有關方法的更多資訊和示例,請參閱方法定義。
計算屬性名
物件初始化器語法還支援計算屬性名。這允許你在方括號 [] 中放置一個表示式,該表示式將被計算並用作屬性名。這讓人聯想到屬性訪問器語法的方括號表示法,你可能已經用它來讀取和設定屬性。
現在你也可以在物件字面量中使用類似的語法了
// Computed property names
let i = 0;
const a = {
[`foo${++i}`]: i,
[`foo${++i}`]: i,
[`foo${++i}`]: i,
};
console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3
const items = ["A", "B", "C"];
const obj = {
[items]: "Hello",
};
console.log(obj); // A,B,C: "Hello"
console.log(obj["A,B,C"]); // "Hello"
const param = "size";
const config = {
[param]: 12,
[`mobile${param.charAt(0).toUpperCase()}${param.slice(1)}`]: 4,
};
console.log(config); // {size: 12, mobileSize: 4}
擴充套件屬性
物件字面量支援擴充套件語法。它將給定物件的可列舉自有屬性複製到新物件上。
現在可以使用比 Object.assign() 更短的語法來實現淺克隆(不包括 prototype)或合併物件。
const obj1 = { foo: "bar", x: 42 };
const obj2 = { foo: "baz", y: 13 };
const clonedObj = { ...obj1 };
// { foo: "bar", x: 42 }
const mergedObj = { ...obj1, ...obj2 };
// { foo: "baz", x: 42, y: 13 }
警告:請注意,Object.assign() 會觸發設定器,而擴充套件語法不會!
原型設定器
形式為 __proto__: value 或 "__proto__": value 的屬性定義不會建立名為 __proto__ 的屬性。相反,如果提供的值是一個物件或 null,它會將建立的物件的 [[Prototype]] 指向該值。(如果該值不是物件或 null,則物件不會改變。)
請注意,__proto__ 鍵是標準化語法,與非標準且效能不佳的 Object.prototype.__proto__ 訪問器形成對比。它在物件建立期間設定 [[Prototype]],類似於 Object.create——而不是改變原型鏈。
const obj1 = {};
console.log(Object.getPrototypeOf(obj1) === Object.prototype); // true
const obj2 = { __proto__: null };
console.log(Object.getPrototypeOf(obj2)); // null
const protoObj = {};
const obj3 = { "__proto__": protoObj };
console.log(Object.getPrototypeOf(obj3) === protoObj); // true
const obj4 = { __proto__: "not an object or null" };
console.log(Object.getPrototypeOf(obj4) === Object.prototype); // true
console.log(Object.hasOwn(obj4, "__proto__")); // false
物件字面量中只允許一個原型設定器。多個原型設定器會導致語法錯誤。
不使用“冒號”表示法的屬性定義不是原型設定器。它們是屬性定義,其行為與使用任何其他名稱的類似定義相同。
const __proto__ = "variable";
const obj1 = { __proto__ };
console.log(Object.getPrototypeOf(obj1) === Object.prototype); // true
console.log(Object.hasOwn(obj1, "__proto__")); // true
console.log(obj1.__proto__); // "variable"
const obj2 = { __proto__() { return "hello"; } };
console.log(obj2.__proto__()); // "hello"
const obj3 = { ["__proto__"]: 17 };
console.log(obj3.__proto__); // 17
// Mixing prototype setter with normal own properties with "__proto__" key
const obj4 = { ["__proto__"]: 17, __proto__: {} }; // {__proto__: 17} (with {} as prototype)
const obj5 = {
["__proto__"]: 17,
__proto__: {},
__proto__: null, // SyntaxError: Duplicate __proto__ fields are not allowed in object literals
};
const obj6 = {
["__proto__"]: 17,
["__proto__"]: "hello",
__proto__: null,
}; // {__proto__: "hello"} (with null as prototype)
const obj7 = {
["__proto__"]: 17,
__proto__,
__proto__: null,
}; // {__proto__: "variable"} (with null as prototype)
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-object-initializer |
瀏覽器相容性
載入中…