tässä blogikirjoituksessa tarkastelemme tarkemmin, miten ECMAScript specification näkee JavaScript-objektit. Erityisesti ominaisuudet eivät ole atomisia spec: ssä, vaan koostuvat useista attribuuteista (think fields tietueessa). Jopa dataomaisuuden arvo tallennetaan attribuuttiin!
Sisällysluettelo:
- olioiden rakenne #
- sisäiset lähtöpaikat #
- Omaisuusavaimet #
- Ominaisuusattribuutit #
- Property descriptors #
- hakevat asiasanat ominaisuuksille #
- uusien ominaisuuksien luominen asiasanojen kautta #
- olemassa olevien ominaisuuksien muuttaminen asiasanojen avulla #
- Pitfall: perittyjä lukuominaisuuksia ei voida määrittää #
- API: ominaisuuskuvaukset #
- käyttötapaukset objektille.getOwnPropertyDescriptors () #
- Object.getOwnPropertyDescriptors (): ominaisuuksien kopioiminen objektiin #
- Pitfall: super #
- objekti.getOwnPropertyDescriptors (): kloonausobjektit #
olioiden rakenne #
ECMAScript-spesifikaatiossa olio koostuu:
- sisäiset pelipaikat, jotka ovat tallennuspaikkoja, joihin ei pääse JavaScriptistä, vain määrittelyssä oleviin operaatioihin.
- kokoelma kiinteistöjä. Jokainen ominaisuus liittää avaimen attribuutteihin (ajattele tietueen kenttiä).
sisäiset lähtöpaikat #
näin spesifikaatio kuvaa sisäisiä lähtöpaikkoja (painotus on minun):
- sisäiset lähtöpaikat vastaavat sisäistä tilaa, joka liittyy olioihin ja jota käyttävät erilaiset ECMAScript-spesifikaatioalgoritmit.
- sisäiset raot eivät ole objektin ominaisuuksia, eivätkä ne periydy.
- riippuen erityisestä sisäisestä korttipaikkamäärittelystä tällainen tila voi koostua arvoista:
- mistä tahansa ECMAScript-kielityypistä tai
- tietyistä ECMAScript-määrittelyn tyyppiarvoista.
- ellei nimenomaisesti toisin mainita, sisäiset paikat jaetaan osana olion luomisprosessia, eikä niitä saa dynaamisesti lisätä objektiin.
- ellei toisin mainita, sisäisen korttipaikan alkuarvo on arvo
undefined
. - tämän määrittelyn eri algoritmit luovat objekteja, joilla on sisäisiä lähtö-ja saapumisaikoja. ECMAScript-kieli ei kuitenkaan tarjoa suoraa tapaa liittää sisäisiä aukkoja objektiin.
- sisäiset menetelmät ja sisäiset lähtökohdat yksilöidään tässä eritelmässä käyttäen nimiä, jotka on liitetty kaksinkertaisiin hakasulkeisiin
]
.
on olemassa kahdenlaisia sisäisiä rakoja:
- metodin rakoja objektien manipulointiin (ominaisuuksien saaminen, asetusominaisuudet jne.)
- Data slots with storage (listed in the table below)
Internal data slot | Type |
---|---|
] |
null | object |
] |
boolean |
] |
List of entries |
Descriptions for these data lähtö:
Omaisuusavaimet #
kiinteistön avain on joko:
- merkkijono
- tietoomaisuus tallentaa tietoja. Sen attribuuteilla
value
on jokin JavaScript-arvo. - accessor-ominaisuudella on getter-toiminto ja / tai setter-toiminto. Edellinen on tallennettu attribuuttiin
get
, jälkimmäinen attribuuttiinset
. -
writable
määrittää, voiko dataomaisuuden arvoa muuttaa. -
configurable
määrittää, voiko ominaisuuden attribuutteja muuttaa. Jos se onfalse
, niin:- ominaisuutta ei voi poistaa.
- et voi muuttaa kiinteistöä dataomaisuudesta accessor-omaisuudeksi tai päinvastoin.
- et voi muuttaa mitään muuta ominaisuutta kuin
value
. - kuitenkin vielä yksi attribuutin muutos sallitaan: Voit muuttaa
writable
true
. Anomalian perustelut ovat historialliset: matriisien ominaisuus.length
on aina ollut kirjoitettavissa ja ei-konfiguroitavissa. Kun senwritable
– attribuuttia muutetaan, voidaan ryhmät jäädyttää.
-
enumerable
vaikuttaa joihinkin operaatioihin (kutenObject.assign()
). Jos se onfalse
, nämä toiminnot jättävät ominaisuuden huomiotta.
unnus
Ominaisuusattribuutit #
on kahdenlaisia ominaisuuksia ja niillä on erilaiset attribuutit:
seuraavassa taulukossa on lueteltu kaikki ominaisuusattribuutit.
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:
Property descriptors #
a property descriptor koodaa ominaisuuden attribuutit JavaScript-objektiksi. Niiden TypeScript-rajapinnat näyttävät seuraavilta.
kysymysmerkit osoittavat, että jokainen ominaisuus on valinnainen. Jos jätät ominaisuuden pois, kun siirrät asiasanan toiminnolle, käytetään sen oletusarvoa.
hakevat asiasanat ominaisuuksille #
seuraava koodi hakee asiasanan tiedon ominaisuudelle first
:
seuraavassa esimerkissä haetaan getterin ominaisuuskuvausta fullName
:
käyttämällä desc()
rivillä A on työnäyte niin, että .deepEqual()
toimii.
uusien ominaisuuksien luominen asiasanojen kautta #
voit luoda uusia ominaisuuksia myös ominaisuuskuvausten kautta:
olemassa olevien ominaisuuksien muuttaminen asiasanojen avulla #
Jos oma ominaisuus on jo olemassa, sen määritteleminen asiasanan kautta muuttaa kyseistä ominaisuutta. Toisaalta, joka mahdollistaa Object.defineProperty()
like assignment:
toisaalta voimme myös käyttää Object.defineProperty()
muuttaaksemme dataomaisuuden getteriksi (ja päinvastoin):
Pitfall: perittyjä lukuominaisuuksia ei voida määrittää #
Jos peritty ominaisuus on vain lukuominaisuus, emme voi käyttää määritystä sen muuttamiseen. Perusteluna on, että perityn omaisuuden ohittaminen luomalla oma ominaisuus voidaan nähdä perityn omaisuuden muuttamisena ei-tuhoisasti. Jos kiinteistö ei ole kirjoitettavissa, meidän ei pitäisi pystyä siihen.
Katsotaanpa esimerkkiä:
emme voi muuttaa omaisuutta toimeksiannon kautta. Mutta voimme silti luoda oman ominaisuuden määrittelemällä sen:
Object.defineProperty(obj, 'prop', {value: 2});assert.equal(obj.prop, 2);
Accessor ominaisuuksia, joilla ei ole setteriä, pidetään myös vain luku-ominaisuuksina:
API: ominaisuuskuvaukset #
seuraavien funktioiden avulla voit työskennellä ominaisuuskuvausten kanssa:
käyttötapaukset objektille.getOwnPropertyDescriptors () #
Object.getOwnPropertyDescriptors (): ominaisuuksien kopioiminen objektiin #
ES6: n jälkeen Javascriptillä on jo ollut työkalumenetelmä ominaisuuksien kopioimiseen: Object.assign()
. Tässä menetelmässä käytetään kuitenkin yksinkertaisia get-Ja set-operaatioita sellaisen ominaisuuden kopioimiseen, jonka avain on key
:
target = source;
tämä tarkoittaa, että se luo ominaisuuden uskollisen kopion vain, jos:
- sen attribuutti
writable
ontrue
ja sen attribuuttienumerable
ontrue
(koska näin toimeksianto luo ominaisuuksia). - se on dataomaisuus.
seuraava esimerkki havainnollistaa tätä rajoitusta. Object source
on setteri, jonka avain on data
.
Jos käytämme Object.assign()
kopioimaan omaisuutta data
, niin accessor-ominaisuus data
muutetaan dataomaisuudeksi:
onneksi käyttämällä Object.getOwnPropertyDescriptors()
yhdessä Object.defineProperties()
kopioi uskollisesti ominaisuuden data
:
Pitfall: super
#
super
menetelmä, jossa käytetään super
on kiinteästi yhteydessä kotikohteeseensa (kohteeseen, johon se on tallennettu). Tällä hetkellä ei ole mitään keinoa kopioida tai siirtää tällaista menetelmää toiseen objektiin.
objekti.getOwnPropertyDescriptors (): kloonausobjektit #
pinnallinen Kloonaus muistuttaa kopiointiominaisuuksia, minkä vuoksi Object.getOwnPropertyDescriptors()
on tässäkin hyvä valinta.
kloonin luomiseen käytetään Object.create()
: