多數與物件屬性的互動都可能是 介面層級,包括建立物件常值,以及設定和存取 屬性值。不過,您可以在內部設定 物件,可用於精細控管屬性的存取方式 變造與定義每個物件屬性都有一組隱形屬性 包含與該屬性相關聯的中繼資料,稱為「資源」 。」
與任何屬性相關聯的描述元有兩種類型: 資料描述元和存取子描述元。資料描述元包含 包含屬性值的鍵和值組合,無論這是否 值可寫入、可設定或列舉。存取子描述元包含 在設定、變更或存取屬性時執行的函式。
屬性 | 描述元類型 | 預設值:Object.defineProperty() |
說明 |
---|---|---|---|
[[Value]] |
資料 | undefined |
包含屬性值。 |
[[Writable]] |
資料 | false |
決定您是否可以變更屬性值。 |
[[Get]] |
存取子 | undefined |
屬性的 getter 函式,在 資源用量 |
[[Set]] |
存取子 | undefined |
屬性的 setter 函式,在 。 |
[[Configurable]] |
兩者皆有 | false |
如果這是 false ,就無法刪除屬性及其屬性
屬性無法變更。如果這是 false 且
[[Writable]] 為 true ,則屬性值可以
仍然會變更。 |
[[Enumerable]] |
兩者皆有 | false |
如果這是 true ,您可以對屬性執行疊代作業
for...in 迴圈或 Object.keys() 靜態
方法。 |
這些屬性都使用與 [[Prototype]]
相同的簡寫,指出
這些屬性不供直接存取請改用
Object.defineProperty()
靜態方法,用來定義或修改
物件。Object.defineProperty()
接受三個引數:要執行操作的物件、
要建立或修改的屬性鍵,以及
與所建立或修改的屬性相關聯的描述元。
根據預設,系統會使用 Object.defineProperty()
建立的屬性
無法寫入、列舉或可設定。不過,您建立的任何資源
做為物件常值的一部分,或是使用點號或方括號標記法
可寫入、列舉和可設定。
const myObj = {};
Object.defineProperty(myObj, 'myProperty', {
value: true,
writable: false
});
myObj.myProperty;
> true
myObj.myProperty = false;
myObj.myProperty;
> true
舉例來說,如果 [[Writable]]
有 false
值,就會嘗試設定新的值
在嚴格模式外,關聯屬性失敗並顯示錯誤,並擲回
嚴格模式中的錯誤:
{
const myObj = {};
Object.defineProperty(myObj, 'myProperty', {
value: true,
writable: false
});
myObj.myProperty = false;
myObj.myProperty;
}
> true
(function () {
"use strict";
const myObj = {};
Object.defineProperty(myObj, 'myProperty', {
value: true,
writable: false
});
myObj.myProperty = false;
myObj.myProperty;
}());\
> Uncaught TypeError: "myProperty" is read-only
有效使用描述元是一個相當進階的概念
瞭解物件內部結構至關重要
以更常見方式處理物件相關的語法例如:
這些概念在使用 Object.create()
靜態方法時實際示範。
可讓您精細控管
物件。
Object.create()
會使用現有物件做為物件來建立新物件
原型這可讓新物件沿用其他物件的屬性和方法
使用者定義物件的方法和沿用
JavaScript 內建的 Object
原型。當您透過以下方式叫用 Object.create()
時:
將物件做為引數,就會建立空白物件,且該物件將做為傳送傳遞的物件,
原型
const myCustomPrototype = {
'myInheritedProp': 10
};
const newObject = Object.create( myCustomPrototype );
newObject;
> Object { }
<prototype>: Object { myInheritedProp: 10 }
myInheritedProp: 10
<prototype>: Object { … }
Object.create
可以使用第二個引數,為
使用類似 Object.defineProperty()
的語法來建立新的物件
也就是將鍵對應至一組描述元屬性的物件:
const myCustomPrototype = {
'myInheritedProp': 10
};
const myObj = Object.create( myCustomPrototype, {
myProperty: {
value: "The new property value.",
writable: true,
configurable: true
}
});
myObj;
> Object { … }
myProperty: "The new property value."
<prototype>: Object { myInheritedProp: 10 }
在這個範例中,新物件 (myObj
) 使用物件常值
(myCustomPrototype
) 做為原型,其本身包含沿用而來的
Object.prototype
,因此產生一系列繼承的原型,稱為
原型鏈。每個物件都有原型 (無論指派或沿用的原型)
已指派或沿用本身的原型此連鎖店的結尾為
null
原型,沒有專屬的原型。
const myPrototype = {
'protoProp': 10
};
const newObject = Object.setPrototypeOf( { 'objProp' : true }, myPrototype );
newObject;
> Object { objProp: true }
objProp: true
<prototype>: Object { protoProp: 10 }
protoProp: 10
<prototype>: Object { … }
值原型中包含的屬性會顯示在「頂層」 ,而無需直接存取原型屬性:
const objectLiteral = {
"value" : true
};
objectLiteral;
> Object { value: true }
value: true
<prototype>: Object { … }
objectLiteral.toString();
"[object Object]"
對於與模型關聯的整個原型鏈,此模式皆有效。 物件:嘗試存取屬性時,翻譯器會尋找該屬性 為每個「層級」屬性從上到下直到 找到房源或鏈結結束:
const myCustomPrototype = {
'protoProp': "Prototype property value."
};
const myObj = Object.create( myCustomPrototype, {
myProperty: {
value: "Top-level property value.",
writable: true,
configurable: true
}
});
myObj.protoProp;
> "Prototype property value."
隨堂測驗
哪些描述元是存取子?
[[Get]]
[[Set]]
[[Writable]]