屬性描述元

多數與物件屬性的互動都可能是 介面層級,包括建立物件常值,以及設定和存取 屬性值。不過,您可以在內部設定 物件,可用於精細控管屬性的存取方式 變造與定義每個物件屬性都有一組隱形屬性 包含與該屬性相關聯的中繼資料,稱為「資源」 。」

與任何屬性相關聯的描述元有兩種類型: 資料描述元存取子描述元。資料描述元包含 包含屬性值的鍵和值組合,無論這是否 值可寫入、可設定或列舉。存取子描述元包含 在設定、變更或存取屬性時執行的函式。

屬性 描述元類型 預設值:
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]]