i dette blogindlæg ser vi nærmere på, hvordan ECMAScript-specifikationen ser JavaScript-objekter. Især er egenskaber ikke atomiske i specifikationen, men sammensat af flere attributter (tænk felter i en post). Selv værdien af en dataegenskab gemmes i en attribut!
Indholdsfortegnelse:
- strukturen af objekter #
- interne slots #
- Egenskabsnøgler #
- Egenskabsattributter #
- Ejendomsdeskriptorer #
- henter deskriptorer for egenskaber #
- oprettelse af nye egenskaber via deskriptorer #
- ændring af eksisterende egenskaber via deskriptorer #
- faldgrube: arvelige skrivebeskyttede egenskaber kan ikke tildeles #
- API: ejendomsdeskriptorer #
- brug sager til objekt.Hent propertydescriptors () #
- objekt.Hent propertydescriptors (): kopiering af egenskaber til et objekt #
- faldgrube: kopieringsmetoder, der bruger super #
- objekt.Hent propertydescriptors (): kloning af objekter #
strukturen af objekter #
i ECMAScript-specifikationen består et objekt af:
- interne slots, som er lagerpladser, der ikke er tilgængelige fra JavaScript, kun til operationer i specifikationen.
- en samling af ejendomme. Hver egenskab knytter en nøgle til attributter (tænk felter i en post).
interne slots #
sådan beskriver specifikationen interne slots (vægten er min):
- interne slots svarer til intern tilstand, der er forbundet med objekter og bruges af forskellige ECMAScript-specifikationsalgoritmer.
- interne slots er ikke objektegenskaber, og de arves ikke.
- afhængigt af den specifikke interne slotspecifikation kan en sådan tilstand bestå af værdier:
- af enhver ECMAScript-sprogtype eller
- af specifikke ECMAScript-specifikationstypeværdier.
- medmindre andet udtrykkeligt er angivet, tildeles interne slots som en del af processen med at oprette et objekt og føjes muligvis ikke dynamisk til et objekt.
- medmindre andet er angivet, er den oprindelige værdi af en intern slot værdien
undefined
. - forskellige algoritmer inden for denne specifikation skaber objekter, der har interne slots. ECMAScript-sproget giver dog ingen direkte måde at knytte interne slots til et objekt.
- interne metoder og interne slots identificeres inden for denne specifikation ved hjælp af navne vedlagt i dobbelt firkantede parenteser
]
.
Der er to slags interne slots:
- metode slots til manipulation af objekter (få egenskaber, indstilling egenskaber, etc.)
- Data slots with storage (listed in the table below)
Internal data slot | Type |
---|---|
] |
null | object |
] |
boolean |
] |
List of entries |
Descriptions for these data slots:
Egenskabsnøgler #
nøglen til en ejendom er enten:
- en streng
- et symbol
Egenskabsattributter #
der er to slags egenskaber, og de har forskellige attributter:
- en dataejendom gemmer data. Dens attributter
value
har enhver JavaScript-værdi. - en accessoregenskab har en getter-funktion og/eller en setter-funktion. Førstnævnte er gemt i attributten
get
, sidstnævnte i attributtenset
.
følgende tabel viser alle egenskabsattributter.
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 value
get
, and set
. The other attributes work as follows:
-
writable
bestemmer, om værdien af en dataegenskab kan ændres. -
configurable
bestemmer, om attributterne for en egenskab kan ændres. Hvis det erfalse
, så:- du kan ikke slette ejendommen.
- du kan ikke ændre en egenskab fra en dataegenskab til en accessoregenskab eller omvendt.
- du kan ikke ændre nogen anden attribut end
value
. - dog er en yderligere attributændring tilladt: Du kan ændre
writable
fratrue
tilfalse
. Begrundelsen bag denne anomali er historisk: ejendom.length
af Arrays har altid været skrivbar og ikke-konfigurerbar. Hvis du tillader, at attributtenwritable
ændres, kan vi fryse Arrays.
-
enumerable
påvirker nogle operationer (såsomObject.assign()
). Hvis det erfalse
, ignorerer disse operationer ejendommen.
Ejendomsdeskriptorer #
en ejendomsdeskriptor koder attributterne for en ejendom som et JavaScript-objekt. Deres TypeScript-grænseflader ser ud som følger.
spørgsmålstegnene angiver, at hver egenskab er valgfri. Hvis du udelader en egenskab, når du sender en deskriptor til en handling, bruges dens standardværdi.
henter deskriptorer for egenskaber #
følgende kode henter objektbeskrivelsen for dataegenskaben first
:
i det næste eksempel henter vi Ejendomsbeskrivelsen for getterfullName
:
Ved hjælp afdesc()
i linje A er en arbejde rundt, så.deepEqual()
virker.
oprettelse af nye egenskaber via deskriptorer #
Du kan også oprette nye egenskaber via ejendomsdeskriptorer:
ændring af eksisterende egenskaber via deskriptorer #
Hvis der allerede findes en egen ejendom, ændres egenskaben ved at definere den via en deskriptor. På den ene side, der giver os mulighed for at bruge Object.defineProperty()
som opgave:
på den anden side kan vi også brugeObject.defineProperty()
for at omdanne en dataegenskab til en getter (og omvendt):
faldgrube: arvelige skrivebeskyttede egenskaber kan ikke tildeles #
Hvis en arvelig egenskab er skrivebeskyttet, kan vi ikke bruge tildeling til at ændre den. Begrundelsen er, at tilsidesættelse af en arvelig ejendom ved at oprette en egen ejendom kan ses som ikke-destruktivt at ændre den arvede ejendom. Formentlig, hvis en ejendom er ikke-skrivbar, bør vi ikke kunne gøre det.
lad os se på et eksempel:
Vi kan ikke ændre egenskaben via tildeling. Men vi kan stadig oprette en egen ejendom ved at definere den:
Object.defineProperty(obj, 'prop', {value: 2});assert.equal(obj.prop, 2);
Accessoregenskaber, der ikke har en setter, betragtes også som skrivebeskyttede:
API: ejendomsdeskriptorer #
følgende funktioner giver dig mulighed for at arbejde med ejendomsdeskriptorer:
brug sager til objekt.Hent propertydescriptors () #
objekt.Hent propertydescriptors (): kopiering af egenskaber til et objekt #
siden ES6 har JavaScript allerede haft en værktøjsmetode til kopiering af egenskaber: Object.assign()
. Denne metode bruger dog enkle get og set-operationer til at kopiere en ejendom, hvis nøgle er key
:
target = source;
det betyder, at det kun opretter en trofast kopi af en ejendom, hvis:
- dens attribut
writable
ertrue
og dens attributenumerable
ertrue
(fordi det er sådan, opgave opretter egenskaber). - det er en dataegenskab.
følgende eksempel illustrerer denne begrænsning. Objekt source
har en setter, hvis nøgle erdata
.
Hvis vi bruger Object.assign()
til kopiering af ejendom data
, konverteres tilbehørsegenskaben data
til en dataegenskab:
heldigvis bruger Object.getOwnPropertyDescriptors()
sammen med Object.defineProperties()
kopierer trofast ejendommen data
:
faldgrube: kopieringsmetoder, der bruger super
#
en metode, der bruger super
er fast forbundet med sit hjemmeobjekt (det objekt, det er gemt i). Der er i øjeblikket ingen måde at kopiere eller flytte en sådan metode til et andet objekt.
objekt.Hent propertydescriptors (): kloning af objekter #
lav kloning ligner kopieringsegenskaber, hvorfor Object.getOwnPropertyDescriptors()
også er et godt valg her.
for at oprette klonen bruger vi Object.create()
: