Maybaygiare.org

Blog Network

Attributen van objecteigenschappen in JavaScript

in deze blogpost bekijken we hoe de ECMAScript-specificatie JavaScript-objecten ziet. In het bijzonder, eigenschappen zijn niet atomisch in de spec, maar samengesteld uit meerdere attributen (denk velden in een record). Zelfs de waarde van een data-eigenschap wordt opgeslagen in een attribuut!

inhoudsopgave:

de structuur van objecten #

In de ECMAScript-specificatie bestaat een object uit:

  • interne slots, dat zijn opslaglocaties die niet toegankelijk zijn vanuit JavaScript, alleen voor bewerkingen in de specificatie.
  • een verzameling eigenschappen. Elke eigenschap associeert een sleutel met attributen (denk velden in een record).

interne slots #

Dit is hoe de specificatie interne slots beschrijft (de nadruk ligt op mij):

  • interne slots komen overeen met de interne toestand die is geassocieerd met objecten en wordt gebruikt door verschillende ECMAScript-specificatie-algoritmen.
  • interne sleuven zijn geen objecteigenschappen en ze worden niet overgenomen.
  • afhankelijk van de specifieke interne slotspecificatie kan een dergelijke toestand bestaan uit waarden:
    • van elk type ECMAScript-taal of
    • van specifieke waarden van het type ECMAScript-specificatie.
  • tenzij expliciet anders aangegeven, worden interne slots toegewezen als onderdeel van het proces van het maken van een object en mogen ze niet dynamisch aan een object worden toegevoegd.
  • tenzij anders aangegeven, is de beginwaarde van een intern slot de waarde undefined.
  • verschillende algoritmen binnen deze specificatie maken objecten met interne sleuven. De ECMAScript-taal biedt echter geen directe manier om interne slots te associëren met een object.
  • interne methoden en interne sleuven worden binnen deze specificatie geïdentificeerd aan de hand van Namen tussen dubbele vierkante haken ].

Er zijn twee soorten interne sleuven:

  • Method sleuven voor het manipuleren van objecten (eigenschappen ophalen, eigenschappen instellen, enz.)
  • Data slots with storage (listed in the table below)
Internal data slot Type
] null | object
] boolean
] List of entries

Descriptions for these data slots:

Eigenschappentoetsen #

de sleutel van een eigenschap is ofwel:

  • een tekenreeks
  • een symbool

Eigenschapkenmerken #

Er zijn twee soorten eigenschappen die verschillende kenmerken hebben:

  • een gegevenseigenschap slaat gegevens op. De attributen value bevatten elke JavaScript-waarde.
  • een accessor-eigenschap heeft een getter-functie en / of een setter-functie. De eerste wordt opgeslagen in het attribuut get, de laatste in het attribuut set.

de volgende tabel toont alle eigenschappen.

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 bepaalt of de waarde van een gegevenseigenschap kan worden gewijzigd.
  • configurable bepaalt of de attributen van een eigenschap kunnen worden gewijzigd. Als het false is, dan:
    • u kunt de eigenschap niet verwijderen.
    • u kunt een eigenschap niet wijzigen van een data-eigenschap naar een accessor-eigenschap of omgekeerd.
    • u kunt geen andere attributen wijzigen dan value.
    • echter, één attribuutwijziging is toegestaan: U kunt writable veranderen van naar false. De reden achter deze anomalie is historisch: eigenschap .length van Arrays is altijd beschrijfbaar en niet-configureerbaar geweest. Als het writable attribuut gewijzigd wordt, kunnen we Arrays bevriezen.
  • enumerable beïnvloedt sommige bewerkingen (zoals Object.assign()). Als het false is, dan negeren deze bewerkingen de eigenschap.

Property descriptors #

een property descriptor codeert de attributen van een property als een JavaScript-object. Hun TypeScript interfaces zien er als volgt uit.

de vraagtekens geven aan dat elke eigenschap optioneel is. Als u een eigenschap weglaat bij het doorgeven van een descriptor aan een operatie, dan wordt de standaardwaarde gebruikt.

descriptoren ophalen voor eigenschappen #

de volgende code haalt de objectdescriptor op voor de gegevenseigenschap first:

in het volgende voorbeeld halen we de eigenschap descriptor op voor de getter fullName:

met behulp van desc() In regel A is een work-around zodat .deepEqual() werkt.

nieuwe eigenschappen aanmaken via descriptoren #

u kunt ook nieuwe eigenschappen aanmaken via eigenschapsdescriptoren:

bestaande eigenschappen wijzigen via descriptoren #

als een eigen eigenschap al bestaat, wijzigt het definiëren via een descriptor die eigenschap. Aan de ene kant kunnen we Object.defineProperty() – achtige toewijzing gebruiken:

aan de andere kant kunnen we ook Object.defineProperty() gebruiken om een gegevenseigenschap om te zetten in een getter (en vice versa):

valkuil: overgenomen alleen-lezen eigenschappen kunnen niet worden toegewezen aan #

als een overgenomen eigenschap alleen-lezen is, dan kunnen we geen toewijzing gebruiken om het te veranderen. De grondgedachte is dat het overschrijven van een geërfd eigendom door het creëren van een eigen eigendom kan worden gezien als een niet-destructief veranderen van het geërfd eigendom. Als een eigenschap niet beschrijfbaar is, zouden we dat niet moeten kunnen doen.

laten we eens kijken naar een voorbeeld:

We kunnen de eigenschap niet wijzigen via toewijzing. Maar we kunnen nog steeds een eigen eigenschap maken door deze te definiëren:

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

Accessor-eigenschappen die geen setter hebben, worden ook als alleen-lezen beschouwd:

API: property descriptors #

met de volgende functies kunt u werken met property descriptors:

Use cases for Object.getOwnPropertyDescriptors () #

Object.getOwnPropertyDescriptors (): eigenschappen kopiëren naar een object #

sinds ES6 heeft JavaScript al een gereedschapsmethode voor het kopiëren van eigenschappen: Object.assign(). Deze methode gebruikt echter eenvoudige get-en set-bewerkingen om een eigenschap te kopiëren waarvan de sleutel key:

target = source;

dat betekent dat het alleen een getrouwe kopie van een eigenschap maakt als:

  • het attribuut writable is en zijn attribuut enumerable is (omdat dat is hoe toewijzing eigenschappen creëert).
  • Het is een gegevenseigenschap.

het volgende voorbeeld illustreert deze beperking. Object source heeft een setter waarvan de sleutel datais.

als we Object.assign() gebruiken om eigenschap data te kopiëren, dan wordt de eigenschap data geconverteerd naar een gegevenseigenschap:

Gelukkig wordt Object.getOwnPropertyDescriptors() samen met Object.defineProperties() kopieert de eigenschap getrouw data:

valkuil: kopieermethoden die super #

een methode die super gebruikt, is stevig verbonden met het eigen object (het object waarin het is opgeslagen). Er is momenteel geen manier om een dergelijke methode te kopiëren of te verplaatsen naar een ander object.

Object.getOwnPropertyDescriptors (): cloning objects #

ondiep klonen is vergelijkbaar met kopieereigenschappen, daarom is Object.getOwnPropertyDescriptors() ook hier een goede keuze.

om de kloon te maken, gebruiken we Object.create():

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.