Deskryptory nieruchomości

Większość interakcji z właściwościami obiektu na poziomie gruntu, w tym do tworzenia literałów obiektów oraz ustawiania i uzyskiwania dostępu za pomocą kluczy. Można jednak wewnętrznie skonfigurować dowolną właściwość obiekt zapewniający szczegółową kontrolę nad sposobem dostępu do tych właściwości, zmienić i zdefiniować. Każda właściwość obiektu ma zestaw niewidocznych atrybutów zawierające metadane powiązane z tą usługą o nazwie „property” deskryptory”.

Z każdą usługą powiązane są 2 typy deskryptorów: deskryptory danych i deskryptory akcesorów. Deskryptor danych zawiera par klucz-wartość, które zawierają wartość właściwości, niezależnie od tego, czy można zapisywać, konfigurować lub wyliczać. Deskryptory akcesorów zawierają funkcji, które są wykonywane po ustawieniu, zmianie lub uzyskaniu dostępu do właściwości.

Właściwość Typ deskryptora Wartość domyślna z
Object.defineProperty()
Opis
[[Value]] Dane undefined Zawiera wartość właściwości.
[[Writable]] Dane false Określa, czy możesz zmienić wartość właściwości.
[[Get]] akcesor undefined Funkcja getter właściwości, która jest wykonywana, gdy usługi.
[[Set]] akcesor undefined Funkcja setter właściwości, która jest wykonywana, gdy właściwość jest ustawiona lub zmieniona.
[[Configurable]] Obie opcje false Jeśli jest to false, usługi nie można usunąć ani jej nie można zmieniać atrybutów. Jeśli jest to false i [[Writable]] to true, wartość właściwości może można zmienić.
[[Enumerable]] Obie opcje false Jeśli ma to wartość true, możesz iterować usługę za pomocą funkcji pętle for...in lub statyczny Object.keys() .

Każda z tych właściwości używa tego samego skrótu co [[Prototype]], co wskazuje że dostęp do tych usług nie jest możliwy bezpośrednio. Zamiast tego użyj Metoda statyczna Object.defineProperty() do definiowania lub modyfikowania właściwości obiektu. Funkcja Object.defineProperty() akceptuje 3 argumenty: obiekt, na którym działa, klucz właściwości, który ma zostać utworzony lub zmodyfikowany, oraz obiekt zawierający deskryptory powiązane z tworzoną lub modyfikowaną usługą.

Domyślnie usługi tworzone za pomocą usługi Object.defineProperty() nie można zapisywać, wyliczać ani konfigurować. Jednak każda usługa, którą utworzysz, jako część literału obiektu lub przy użyciu notacji kropki bądź nawiasu możliwy do zapisu, wyliczania i konfigurowania.

const myObj = {};

Object.defineProperty(myObj, 'myProperty', {
  value: true,
  writable: false
});

myObj.myProperty;
> true

myObj.myProperty = false;

myObj.myProperty;
> true

Jeśli na przykład [[Writable]] ma wartość false, próba ustawienia nowej wartości dla powiązanej usługi przechodzi dyskryminację poza trybem ścisłym i zwraca w trybie ścisłym:

{
    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

Efektywne korzystanie z deskryptorów to dość zaawansowana koncepcja, zrozumienie struktury wewnętrznej obiektu jest kluczem do zrozumienia składni używanych podczas pracy z obiektami na bardziej popularne sposoby. Przykład: te pojęcia wchodzą w życie podczas korzystania z metody statycznej Object.create(), co daje precyzyjną kontrolę nad wszelkimi prototypami połączonymi obiektu.

Object.create() tworzy nowy obiekt, używając istniejącego obiektu jako obiektu i prototypem. Dzięki temu nowy obiekt odziedziczy właściwości i metody z innego obiektu zdefiniowanego przez użytkownika w taki sam sposób, w jaki obiekty dziedziczą właściwości z obiektu Wbudowany prototyp języka Object w języku JavaScript. Gdy wywołujesz aplikację Object.create() z: obiektu jako argumentu, tworzy pusty obiekt z przekazanym obiektem jako swojego prototypu.

const myCustomPrototype = {
  'myInheritedProp': 10
};

const newObject = Object.create( myCustomPrototype );

newObject;
> Object {  }
<prototype>: Object { myInheritedProp: 10 }
  myInheritedProp: 10
  <prototype>: Object { … }

Funkcja Object.create może przyjąć drugi argument określający własne właściwości obiektu nowo utworzonego obiektu o składni podobnej do Object.defineProperty(): czyli kluczy mapowania obiektów do zestawu atrybutów deskryptora:

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 }

W tym przykładzie nowy obiekt (myObj) używa literału obiektu (myCustomPrototype) jako prototyp, który zawiera odziedziczone Object.prototype, w wyniku czego powstała szereg odziedziczonych prototypów łańcuch prototypów. Każdy obiekt ma prototyp – nieważne, czy jest przypisany, czy dziedziczony. który ma przypisany lub odziedziczony prototyp. Ta sieć kończy się o Prototyp null, który nie ma własnego prototypu.

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 { … }

Właściwości zawarte w prototypie wartości są dostępne na „najwyższym poziomie” bez konieczności bezpośredniego dostępu do właściwości prototypu:

const objectLiteral = {
    "value" : true
};

objectLiteral;
> Object { value: true }
    value: true
    <prototype>: Object { … }

objectLiteral.toString();
"[object Object]"

Ten wzorzec odnosi się do całego łańcucha prototypów powiązanego z obiektu: gdy próbuje uzyskać dostęp do właściwości, tłumacz usługę na poszczególnych „poziomach” prototypowego łańcucha (od góry do dołu), znajduje właściwość lub kończy się łańcuch:

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."

Sprawdź swoją wiedzę

Które deskryptory są akcesorami?

[[Get]]
[[Set]]
[[Writable]]