10. Destruktion
10. Destruktion #
- 10.1. Oversigt
- 10.1.1. Objekt ødelæggelse
- 10.1.2. Array destrukturering
- 10.1.3. Hvor kan destrukturering bruges?
- 10.2. Baggrund: konstruktion af data versus udtrækning af data
- 10.3. Mønstre til destruktion
- 10.3.1. Vælg hvad du har brug for
- 10.4. Hvordan får mønstre adgang til indersiden af værdier?
- 10.4.1. Objektmønstre tvinger værdier til objekter
- 10.4.2. Array mønstre arbejde med iterables
- 10.5. Standardværdier
- 10.5.1.
undefined
udløser standardværdier - 10.5.2. Standardværdier beregnes efter behov
- 10.5.3. Standardværdier kan henvise til andre variabler i mønsteret
- 10.5.4. Standardværdier for mønstre
- 10.5.5. Mere komplekse standardværdier
- 10.5.1.
- 10.6. Flere objekt destrukturering funktioner
- 10.6.1. Ejendom værdi shorthands
- 10.6.2. Beregnede ejendomsnøgler
- 10.7. Flere array destrukturering funktioner
- 10.7.1. Elision
- 10.7.2. Rest operator (
...
)
- 10.8. Du kan tildele mere end blot variabler
- 10.9. Faldgruber af destrukturering
- 10.9.1. Start ikke en erklæring med en krøllet bøjle
- 10.10. Eksempler på destruktion
- 10.10.1. Destrukturering returnerede Arrays
- 10.10.2. Destrukturering returnerede objekter
- 10.10.3. Array-destrukturering iterable værdier
- 10.10.4. Flere returværdier
- 10.11. Destruktureringsalgoritmen
- 10.11.1. Algoritmen
- 10.11.2. Anvendelse af algoritmen
10.1 oversigt #
Destrukturering er en bekvem måde at udtrække flere værdier fra data gemt i (muligvis indlejrede) objekter og Arrays. Det kan bruges på steder, der modtager data (f.eks. i venstre side af en opgave). Sådan udtrækkes værdierne specificeres via mønstre (læs videre for eksempler).
10.1.1 objekt destrukturering #
Destrukturering objekter:
Destrukturering hjælper med behandling af returværdier:
10.1.2 Array destrukturering #
Array destrukturering (virker for alle iterable værdier):
Destrukturering hjælper med behandling af returværdier:
10.1.3 Hvor kan destrukturering bruges? #
Destrukturering kan bruges på følgende steder (jeg viser Array mønstre for at demonstrere; objekt mønstre fungerer lige så godt):
du kan også destruere i en for-of
loop:
10.2 baggrund: konstruktion af data versus udtrækning af data #
for fuldt ud at forstå, hvad destrukturering er, lad os først undersøge dens bredere kontekst.
JavaScript har operationer til konstruktion af data, en ejendom ad gangen:
den samme syntaks kan bruges til at udtrække data. Igen, en ejendom ad gangen:
derudover er der syntaks til at konstruere flere egenskaber på samme tid via et objekt bogstaveligt:
før ES6 var der ingen tilsvarende mekanisme til udvinding af data. Det er hvad destrukturering er-det giver dig mulighed for at udtrække flere egenskaber fra et objekt via et objektmønster. For eksempel på venstre side af en opgave:
du kan også destruere Arrays via mønstre:
10.3 mønstre til destrukturering #
følgende to parter er involveret i destrukturering:
- Destruktureringskilde: de data, der skal destrueres. For eksempel højre side af en destruktureringsopgave.
- Destruktureringsmål: mønsteret anvendt til destrukturering. For eksempel venstre side af en destruktureringsopgave.
destruktureringsmålet er enten et af tre mønstre:
- opgave mål. For eksempel:
x
- et tildelingsmål er normalt en variabel. Men i destrukturering opgave, du har flere muligheder, som jeg vil forklare senere.
- objekt mønster. For eksempel:
{ first: "pattern", last: "pattern" }
- dele af et objektmønster er egenskaber, egenskabsværdierne er igen mønstre (rekursivt).
- Array mønster. For eksempel:
- dele af et Array mønster er elementer, elementerne er igen mønstre (rekursivt).
det betyder, at du kan rede mønstre, vilkårligt dybt:
10.3.1 Vælg hvad du har brug for #
hvis du ødelægger et objekt, nævner du kun de egenskaber, du er interesseret i:
hvis du destruerer et Array, kan du vælge kun at udtrække et præfiks:
10.4 Hvordan får mønstre adgang til indersiden af værdier? #
i en opgave pattern = someValue
, hvordan får pattern
adgang til hvad der er indeni someValue
?
10.4.1 Objektmønstre tvinger værdier til objekter #
objektmønsteret tvinger destrueringskilder til objekter, før de får adgang til Egenskaber. Det betyder, at det fungerer med primitive værdier:
10.4.1.1 manglende objekt-destrukturering af en værdi #
tvang til objekt udføres ikke via Object()
, men via den interne operation ToObject()
. De to operationer håndterer undefined
og null
forskelligt.
Object()
konverterer primitive værdier til indpakning objekter og efterlader objekter uberørt:
It also converts undefined
and null
to empty objects:
In contrast, ToObject()
throws a TypeError
if it encounters undefined
or null
. Therefore, the following destructurings fail, even before destructuring accesses any properties:
som følge heraf kan du bruge det tomme objektmønster {}
til at kontrollere, om en værdi kan tvinges til et objekt. Som vi har set, er kun undefined
og null
ikke:
parenteserne omkring udtrykkene er nødvendige, fordi udsagn ikke må begynde med krøllede seler i JavaScript (detaljer forklares senere).
10.4.2 Array mønstre arbejde med iterables #
Array destrukturering bruger en iterator til at komme til elementerne i en kilde. Derfor kan du array-destrukturere enhver værdi, der kan gentages. Lad os se på eksempler på iterable værdier.
strenge er iterable:
glem ikke, at iteratoren over strenge returnerer kodepunkter (“Unicode-tegn”, 21 bit), ikke kodeenheder (“JavaScript-tegn”, 16 bit). (For mere information om Unicode, se kapitlet ” Kapitel 24. Unicode og JavaScript ” i “talende JavaScript”.) For eksempel:
du kan ikke få adgang til elementerne i et sæt via indekser, men du kan gøre det via en iterator. Derfor arbejder array destructuring for sæt:
Set
iteratoren returnerer altid elementer i den rækkefølge, de blev indsat i, hvorfor resultatet af den tidligere destrukturering altid er det samme.
10.4.2.1 manglende array-destrukturering af en værdi #
en værdi kan gentages, hvis den har en metode, hvis nøgle er Symbol.iterator
, der returnerer et objekt. Array-destrukturering kaster en TypeError
hvis værdien, der skal destrueres, ikke kan gentages:
TypeError
kastes, selv før du får adgang til elementer i iterable, hvilket betyder, at du kan bruge det tomme Array mønster for at kontrollere, om en værdi er iterable:
10.5 standardværdier #
standardværdier er en valgfri funktion af mønstre. De giver en tilbagegang, hvis der ikke findes noget i kilden. Hvis en del (en objektegenskab eller et Array-element) ikke har nogen match i kilden, matches den mod:
- dens standardværdi (hvis angivet; det er valgfrit)
-
undefined
(ellers)
lad os se på et eksempel. I den følgende destrukturering har elementet ved indeks 0 ingen match på højre side. Derfor fortsætter destrukturering ved at matche x
mod 3, hvilket fører til, at x
er indstillet til 3.
du kan også bruge standardværdier i objektmønstre:
10.5.1 undefined
udløser standardværdier #
standardværdier bruges også, hvis en del har et match, og det match er undefined
:
begrundelsen for denne adfærd forklares i det næste kapitel i afsnittet om parameterstandardværdier.
10.5.2 standardværdier beregnes efter behov #
selve standardværdierne beregnes kun, når de er nødvendige. Med andre ord, denne ødelæggelse:
svarer til:
du kan observere, at hvis du bruger console.log()
:
In the second destructuring, the default value is not triggered and log()
is not called.
10.5.3 Default values can refer to other variables in the pattern #
A default value can refer to any variable, including other variables in the same pattern:
imidlertid, ordre betyder noget: variablerne x
og y
erklæres fra venstre mod højre og producerer en ReferenceError
, hvis de er tilgængelige før deres erklæringer:
10.5.4 standardværdier for mønstre #
indtil videre har vi kun set standardværdier for variabler, men du kan også knytte dem til mønstre:
hvad betyder det? Husk reglen for standardværdier: hvis en del ikke har noget match i kilden, fortsætter destruktureringen med standardværdien.
elementet ved indeks 0 har ingen match, hvorfor destrukturering fortsætter med:
du kan lettere se, hvorfor tingene fungerer på denne måde, hvis du erstatter mønsteret { prop: x }
med variablen pattern
:
10.5.5 mere komplekse standardværdier #
lad os yderligere undersøge standardværdier for mønstre. I det følgende eksempel tildeler vi en værdi til x
via standardværdien { prop: 123 }
:
da arrayelementet ved indeks 0 ikke har nogen match på højre side, fortsætter destruktureringen som følger, og x
er indstillet til 123.
x
tildeles dog ikke en værdi på denne måde, hvis højre side har et element ved indeks 0, fordi standardværdien ikke udløses.
i dette tilfælde fortsætter ødelæggelsen med:
Således, hvis du vil have x
til at være 123, hvis enten objektet eller ejendommen mangler, skal du angive en standardværdi for x
selv:
her fortsætter destruktureringen som følger, uafhængigt af om højre side er eller
.
10.6 flere objekt destrukturering funktioner #
10.6.1 egenskabsværdi shorthands #
egenskabsværdi shorthands er en funktion af objekt literals: Hvis egenskabsværdien er en variabel, der har samme navn som egenskabsnøglen, kan du udelade nøglen. Dette fungerer også til destruktion:
du kan også kombinere egenskabsværdi shorthands med standardværdier:
10.6.2 beregnede egenskabsnøgler #
beregnede egenskabsnøgler er en anden objekt bogstavelig funktion, der også virker til destruktion. Du kan angive nøglen til en ejendom via et udtryk, hvis du sætter det i firkantede parenteser:
beregnede egenskabsnøgler giver dig mulighed for at destruere egenskaber, hvis nøgler er symboler:
10.7 flere Array destrukturering funktioner #
10.7.1 Elision #
Elision lader dig bruge syntaksen af Array “huller” til at springe elementer under destruering:
10.7.2 Rest operator (...
) #
resten operatør kan du udtrække de resterende elementer i en iterable i et Array. Hvis denne operatør bruges inde i et Array mønster, skal det komme sidst:
hvis operatøren ikke kan finde nogen elementer, matcher den sin operand mod det tomme Array. Det vil sige, det producerer aldrig undefined
eller null
. For eksempel:
resten operatørens operand behøver ikke at være en variabel, du kan også bruge mønstre:
resten operatør udløser følgende destrukturering:
10.8 Du kan tildele mere end blot variabler #
hvis du tildeler via destrukturering, kan hvert tildelingsmål være alt, hvad der er tilladt på venstre side af en normal tildeling.
for eksempel en henvisning til en ejendom (obj.prop
):
eller en henvisning til et Array element (arr
):
du kan også tildele objektegenskaber og Array-elementer via rest-operatøren (...
):
hvis du erklærer variabler eller definerer parametre via destrukturering, skal du bruge enkle identifikatorer, du kan ikke henvise til objektegenskaber og arrayelementer.
10.9 faldgruber af destrukturering #
der er to ting at være opmærksom på, når du bruger destrukturering:
- du kan ikke starte en erklæring med en krøllet bøjle.
- under destrukturering kan du enten erklære variabler eller tildele dem, men ikke begge dele.
de næste to afsnit indeholder detaljerne.
10.9.1 start ikke en erklæring med en krøllet bøjle #
da kodeblokke begynder med en krøllet bøjle, må udsagn ikke begynde med en. Dette er uheldigt, når du bruger objektdestrukturering i en opgave:
arbejdet er at sætte det komplette udtryk i parentes:
følgende syntaks virker ikke:
med let
, var
og const
forårsager krøllede seler aldrig problemer:
10.10 Eksempler på destrukturering #
lad os starte med et par mindre eksempler.
den for-of
loop understøtter destrukturering:
du kan bruge destrukturering til at bytte værdier. Det er noget, som motorer kunne optimere, så der ikke oprettes noget Array.
du kan bruge destrukturering til at opdele et Array:
10.10.1 Destrukturering returnerede Arrays #
nogle indbyggede JavaScript-operationer returnerer Arrays. Destrukturering hjælper med at behandle dem:
hvis du kun er interesseret i grupperne (og ikke i det komplette match, all
), kan du bruge elision til at springe array-elementet over ved indeks 0:
exec()
returnerer null
, hvis det regulære udtryk ikke stemmer overens. Desværre kan du ikke håndtere null
via standardværdier, hvorfor du skal bruge or-operatøren (||
) i dette tilfælde:
Array.prototype.split()
returnerer et Array. Derfor er destrukturering nyttig, hvis du er interesseret i elementerne, ikke arrayet:
10.10.2 Destrukturering returnerede objekter #
Destrukturering er også nyttig til at udtrække data fra objekter, der returneres af funktioner eller metoder. For eksempel returnerer iteratormetoden next()
et objekt med to egenskaber, done
og value
. Følgende kode logger alle elementer i Array arr
via iteratoren iter
. Destrukturering anvendes i linje A.
10.10.3 Array-destrukturering iterable værdier #
Array-destrukturering arbejder med enhver iterable værdi. Det er lejlighedsvis nyttigt:
10.10.4 flere returværdier #
for at se nytten af flere returværdier, lad os implementere en funktion findElement(a, p)
, der søger efter det første element i arrayet a
, som funktionen p
returnerer true
. Spørgsmålet er: hvad skal findElement()
vende tilbage? Nogle gange er man interesseret i selve elementet, nogle gange i sit indeks, nogle gange i begge. Følgende implementering returnerer begge dele.
funktionen gentager over alle elementer af array
via Array-metoden entries()
, som returnerer en iterabel over par (linje A). Parrets dele er tilgængelige via destruktion.
lad os bruge findElement()
:
flere ECMAScript 6 funktioner tillod os at skrive mere kortfattet kode: tilbagekaldelsen er en pilfunktion; returværdien ødelægges via et objektmønster med ejendomsværdi shorthands.
på grund af index
og element
henviser også til egenskabsnøgler, den rækkefølge, vi nævner dem i, betyder ikke noget. Vi kan bytte dem, og intet ændrer sig:
vi har med succes håndteret sagen om at have brug for både indeks og element. Hvad hvis vi kun er interesseret i en af dem? Det viser sig, at takket være ECMAScript 6 kan vores implementering også tage sig af det. Og den syntaktiske overhead sammenlignet med funktioner med enkelt returværdier er minimal.
hver gang udvinder vi kun værdien af den ene ejendom, vi har brug for.
10.11 destruktureringsalgoritmen #
dette afsnit ser på destrukturering fra en anden vinkel: som en rekursiv mønstertilpasningsalgoritme.
i slutningen bruger jeg algoritmen til at forklare forskellen mellem de følgende to funktionserklæringer.
10.11.1 algoritmen #
en destruktureringsopgave ser sådan ud:
vi vil bruge pattern
til at udtrække data fra value
. Jeg vil nu beskrive en algoritme til at gøre det, som er kendt i funktionel programmering som mønstertilpasning (kort: matching). Algoritmen specificerer operatøren ←
(“match mod”) til destruktureringstildeling, der matcher en pattern
mod en value
og tildeler variabler, mens du gør det:
algoritmen er specificeret via rekursive regler, der adskiller begge operander af ←
operatoren. Den deklarative notation kan tage noget at vænne sig til, men det gør specifikationen af algoritmen mere kortfattet. Hver regel har to dele:
- hovedet (første linje) beskriver den tilstand, der udløser reglen.
- kroppen (resterende linjer) beskriver, hvad der sker, hvis reglen udløses.
lad os se på et eksempel:
- (2c)
{key: "pattern", "properties"} ← obj
- (2e)
{} ← obj
(ingen ejendomme tilbage)
i regel (2C) betyder hovedet, at denne regel udføres, hvis der er et objektmønster med mindst en egenskab og nul eller flere resterende egenskaber. Dette mønster matches med en værdi obj
. Effekten af denne regel er, at udførelsen fortsætter med, at egenskabsværdimønsteret matches med obj.key
, og de resterende egenskaber matches med obj
.
i regel (2e) betyder hovedet, at denne regel udføres, hvis det tomme objektmønster {}
matches med en værdi obj
. Så er der intet at gøre.
når algoritmen påberåbes, kontrolleres reglerne top til bund, og kun den første regel, der gælder, udføres.
jeg viser kun algoritmen til destrukturering opgave. Destrukturering variable erklæringer og destrukturering parameter definitioner arbejde på samme måde.
jeg dækker ikke avancerede funktioner (beregnede ejendomsnøgler; ejendomsværdi shorthands; objektegenskaber og array-elementer som tildelingsmål), enten. Kun det grundlæggende.
10.11.1.1 mønstre #
et mønster er enten:
- en variabel:
x
- et objekt mønster:
{"properties"}
- et Array mønster:
hvert af de følgende afsnit beskriver et af disse tre tilfælde.
de følgende tre afsnit angiver, hvordan disse tre sager skal håndteres. Hvert afsnit indeholder en eller flere nummererede regler.
10.11.1.2 variabel #
- (1)
x ← value
(herunderundefined
ognull
)
10.11.1.3 objekt mønster #
- (2a)
{"properties"} ← undefined
- (2b)
{"properties"} ← null
- (2c)
{key: "pattern", "properties"} ← obj
- (2d)
{key: "pattern" = default_value, "properties"} ← obj
- (2e)
{} ← obj
(ingen ejendomme tilbage)
10.11.1.4 Array mønster #
Array mønster og iterable. Algoritmen til array destrukturering starter med et Array mønster og en iterable:
- (3a)
← non_iterable
assert(!isIterable(non_iterable))
- (3b)
← iterable
assert(isIterable(iterable))
hjælper funktion:
Array elementer og iterator. Algoritmen fortsætter med elementerne i mønsteret (venstre side af pilen) og iteratoren, der blev opnået fra den iterable (højre side af pilen).
- (3c)
"pattern", "elements" ← iterator
- (3d)
"pattern" = default_value, "elements" ← iterator
- (3e)
, "elements" ← iterator
(hul, elision)
- (3f)
..."pattern" ← iterator
( altid sidste del!)
- (3g)
← iterator
(ingen elementer tilbage)
hjælper funktion:
10.11.2 anvendelse af algoritmen #
i ECMAScript 6 kan du simulere navngivne parametre, hvis den, der ringer op, bruger et objekt bogstaveligt, og callee bruger destrukturering. Denne simulering forklares detaljeret i kapitlet om parameterhåndtering. Følgende kode viser et eksempel: funktion move1()
har to navngivne parametre, x
og y
:
der er tre standardværdier i linje A:
- de to første standardværdier giver dig mulighed for at udelade
x
ogy
. - den tredje standardværdi giver dig mulighed for at ringe
move1()
uden parametre (som i den sidste linje).
men hvorfor ville du definere parametrene som i det foregående kodestykke? Hvorfor ikke som følger-hvilket også er helt lovligt ES6 kode?
for at se hvorfor move1()
er korrekt, lad os bruge begge funktioner til to eksempler. Før vi gør det, lad os se, hvordan passering af parametre kan forklares via matching.
10.11.2.1 baggrund: passerer parametre via matchende #
for funktionsopkald matches formelle parametre (indvendige funktionsdefinitioner) med faktiske parametre (indvendige funktionsopkald). Tag som eksempel følgende funktionsdefinition og følgende funktionsopkald.
parametrene a
og b
er sat op på samme måde som følgende destrukturering.
10.11.2.2 brug af move2()
#
lad os undersøge, hvordan destrukturering virker for move2()
.
eksempel 1. move2()
fører til denne ødelæggelse:
det enkelte arrayelement på venstre side har ikke en match på højre side, hvorfor {x,y}
matches mod standardværdien og ikke mod data fra højre side (regler 3b, 3d):
den venstre side indeholder ejendomsværdi shorthands, det er en forkortelse for:
denne destrukturering fører til følgende to opgaver (regler 2C, 1):
eksempel 2. Lad os undersøge funktionskaldet move2({z:3})
, som fører til følgende ødelæggelse:
der er et Array element ved indeks 0 på højre side. Derfor ignoreres standardværdien, og det næste trin er (regel 3d):
det fører til, at både x
og y
er indstillet til undefined
, hvilket ikke er det, vi ønsker.
10.11.2.3 brug af move1()
#
lad os prøve move1()
.
eksempel 1: move1()
vi har ikke et Array-element ved indeks 0 på højre side og bruger standardværdien (regel 3d):
den venstre side indeholder ejendomsværdi shorthands, hvilket betyder, at denne destrukturering svarer til:
hverken ejendom x
eller ejendom y
har et match på højre side. Derfor anvendes standardværdierne, og følgende ødelæggelser udføres næste (regel 2D):
det fører til følgende opgaver (regel 1):
eksempel 2: move1({z:3})
det første element i Arraymønsteret har en kamp på højre side, og den kamp bruges til at fortsætte destruktureringen (regel 3d):
som I eksempel 1 er der ingen egenskaber x
og y
på højre side, og standardværdierne bruges:
10.11.2.4 konklusion #
eksemplerne viser, at standardværdier er en funktion af mønsterdele (objektegenskaber eller arrayelementer). Hvis en del ikke har noget match eller matches med undefined
, bruges standardværdien. Det vil sige, at mønsteret matches med standardværdien i stedet.