Maybaygiare.org

Blog Network

Attribute von Objekteigenschaften in JavaScript

In diesem Blogbeitrag werfen wir einen genaueren Blick darauf, wie die ECMAScript-Spezifikation JavaScript-Objekte sieht. Insbesondere sind Eigenschaften in der Spezifikation nicht atomar, sondern bestehen aus mehreren Attributen (denken Sie an Felder in einem Datensatz). Sogar der Wert einer Dateneigenschaft wird in einem Attribut gespeichert!

Inhaltsverzeichnis:

Die Struktur von Objekten #

In der ECMAScript-Spezifikation besteht ein Objekt aus:

  • Interne Steckplätze, die Speicherorte sind, auf die von JavaScript aus nicht zugegriffen werden kann, nur für Vorgänge in der Spezifikation.
  • Eine Sammlung von Eigenschaften. Jede Eigenschaft verknüpft einen Schlüssel mit Attributen (denken Sie an Felder in einem Datensatz).

Interne Slots #

So beschreibt die Spezifikation interne Slots (die Betonung liegt bei mir):

  • Interne Slots entsprechen dem internen Status, der Objekten zugeordnet ist und von verschiedenen ECMAScript-Spezifikationsalgorithmen verwendet wird.
  • Interne Slots sind keine Objekteigenschaften und werden nicht vererbt.
  • Abhängig von der spezifischen internen Steckplatzspezifikation kann ein solcher Status aus folgenden Werten bestehen:
    • eines beliebigen ECMAScript-Sprachtyps oder
    • bestimmter ECMAScript-Spezifikationstypwerte.
  • Sofern nicht ausdrücklich anders angegeben, werden interne Slots als Teil des Erstellungsprozesses eines Objekts zugewiesen und dürfen einem Objekt nicht dynamisch hinzugefügt werden.
  • Sofern nicht anders angegeben, ist der Anfangswert eines internen Steckplatzes der Wert undefined.
  • Verschiedene Algorithmen innerhalb dieser Spezifikation erzeugen Objekte mit internen Slots. Die ECMAScript-Sprache bietet jedoch keine direkte Möglichkeit, interne Slots einem Objekt zuzuordnen.
  • Interne Methoden und interne Slots werden innerhalb dieser Spezifikation mit Namen in doppelten eckigen Klammern ] identifiziert.

Es gibt zwei Arten von internen Slots:

  • Methodensteckplätze zum Bearbeiten von Objekten (Abrufen von Eigenschaften, Festlegen von Eigenschaften usw.)
  • Data slots with storage (listed in the table below)
Internal data slot Type
] null | object
] boolean
] List of entries

Descriptions for these data schlüsselwörter:

Property keys #

Der Schlüssel einer Eigenschaft ist entweder:

  • Ein String
  • Ein Symbol

Property attributes #

Es gibt zwei Arten von Eigenschaften und sie haben unterschiedliche Attribute:

  • Eine Dateneigenschaft speichert Daten. Seine Attribute value enthält einen beliebigen JavaScript-Wert.
  • Eine Accessor-Eigenschaft hat eine Getter-Funktion und/oder eine Setter-Funktion. Ersteres wird im Attribut get gespeichert, letzteres im Attribut set.

Die folgende Tabelle listet alle Eigenschaftsattribute auf.

Kind of property Name and type of attribute Default value
Data property value: any undefined
writable: boolean false
Accessor property get(): any undefined
set(v: any): void undefined
All properties configurable: boolean false
enumerable: boolean false

We have already encountered the attributes valueget, and set. The other attributes work as follows:

  • writable bestimmt, ob der Wert einer Dateneigenschaft geändert werden kann.
  • configurable bestimmt, ob die Attribute einer Eigenschaft geändert werden können. Wenn es false , dann:
    • Sie können die Eigenschaft nicht löschen.
    • Sie können eine Eigenschaft nicht von einer Dateneigenschaft in eine Accessor-Eigenschaft oder umgekehrt ändern.
    • Sie können kein anderes Attribut als value ändern.
    • Eine weitere Attributänderung ist jedoch zulässig: Sie können writable von true in false ändern. Der Grund für diese Anomalie ist historisch: Eigenschaft .length von Arrays war immer beschreibbar und nicht konfigurierbar. Wenn wir zulassen, dass das Attribut writable geändert wird, können wir Arrays einfrieren.
  • enumerable beeinflusst einige Operationen (wie Object.assign()). Wenn es false , ignorieren diese Vorgänge die Eigenschaft.

Property descriptors #

Ein Property Descriptor codiert die Attribute einer Eigenschaft als JavaScript-Objekt. Ihre TypeScript-Schnittstellen sehen wie folgt aus.

Die Fragezeichen zeigen an, dass jede Eigenschaft optional ist. Wenn Sie eine Eigenschaft weglassen, wenn Sie einen Deskriptor an eine Operation übergeben, wird der Standardwert verwendet.

Deskriptoren für Eigenschaften abrufen #

Der folgende Code ruft den Objektdeskriptor für die Dateneigenschaft ab first:

Im nächsten Beispiel rufen wir den Eigenschaftsdeskriptor für den Getter fullName ab:

Die Verwendung von desc() in Zeile A ist eine Problemumgehung, sodass .deepEqual() funktioniert.

Erstellen neuer Eigenschaften über Deskriptoren #

Sie können auch neue Eigenschaften über Eigenschaftendeskriptoren erstellen:

Ändern vorhandener Eigenschaften über Deskriptoren #

Wenn bereits eine eigene Eigenschaft vorhanden ist, ändert die Definition über einen Deskriptor diese Eigenschaft. Auf der einen Seite können wir Object.defineProperty() wie folgt verwenden:

Andererseits können wir auch Object.defineProperty() verwenden, um eine Dateneigenschaft in einen Getter umzuwandeln (und umgekehrt):

Fallstrick: Geerbte schreibgeschützte Eigenschaften können nicht zugewiesen werden #

Wenn eine geerbte Eigenschaft schreibgeschützt ist, können wir sie nicht mit der Zuweisung ändern. Der Grund dafür ist, dass das Überschreiben einer geerbten Eigenschaft durch Erstellen einer eigenen Eigenschaft als zerstörungsfreie Änderung der geerbten Eigenschaft angesehen werden kann. Wenn eine Eigenschaft nicht beschreibbar ist, sollten wir das wohl nicht können.

Schauen wir uns ein Beispiel an:

Wir können die Eigenschaft nicht über Zuweisung ändern. Aber wir können immer noch eine eigene Eigenschaft erstellen, indem wir sie definieren:

Object.defineProperty(obj, 'prop', {value: 2});assert.equal(obj.prop, 2);

Accessor-Eigenschaften, die keinen Setter haben, gelten auch als schreibgeschützt:

API: property descriptors #

Mit den folgenden Funktionen können Sie mit Eigenschaftendeskriptoren arbeiten:

Anwendungsfälle für Object .getOwnPropertyDescriptors() #

Objekt.getOwnPropertyDescriptors(): Kopieren von Eigenschaften in ein Objekt #

Seit ES6 hat JavaScript bereits eine Werkzeugmethode zum Kopieren von Eigenschaften: Object.assign() . Diese Methode verwendet jedoch einfache Get- und set-Operationen, um eine Eigenschaft zu kopieren, deren Schlüssel key lautet:

target = source;

Dies bedeutet, dass nur dann eine originalgetreue Kopie einer Eigenschaft erstellt wird, wenn:

  • Das Attribut writabletrue und sein Attribut enumerable ist true (denn so erstellt die Zuweisung Eigenschaften).
  • Es ist eine Dateneigenschaft.

Das folgende Beispiel veranschaulicht diese Einschränkung. Objekt source hat einen Setter, dessen Schlüssel data .

Wenn wir Object.assign() verwenden, um die Eigenschaft data zu kopieren, wird die Accessor-Eigenschaft data in eine Dateneigenschaft konvertiert:

Glücklicherweise wird Object.getOwnPropertyDescriptors() zusammen mit Object.defineProperties() kopiert die Eigenschaft getreu data:

Pitfall: kopieren von Methoden, die super #

verwendenEine Methode, die super verwendet, ist fest mit ihrem Home-Objekt verbunden (dem Objekt, in dem sie gespeichert ist). Derzeit gibt es keine Möglichkeit, eine solche Methode in ein anderes Objekt zu kopieren oder zu verschieben.

Objekt.getOwnPropertyDescriptors(): cloning objects #

Das flache Klonen ähnelt dem Kopieren von Eigenschaften, weshalb Object.getOwnPropertyDescriptors() auch hier eine gute Wahl ist.

Um den Klon zu erstellen, verwenden wir Object.create():

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.