Den valgfrie sammenkædning ?. er en sikker måde at få adgang til indlejrede objekt-egenskaber på, selvom en mellemliggende egenskab ikke eksisterer.
Problemet med “ikke-eksisterende egenskaber”
Hvis du lige er begyndt at læse vejledningen og lære JavaScript, har problemet måske ikke ramt dig endnu, men det er ret almindeligt.
Som et eksempel, lad os sige, at vi har user-objekter, der indeholder oplysninger om vores brugere.
De fleste af vores brugere har adresser i user.address-egenskaben, med gaden user.address.street, men nogle har ikke angivet dem.
I så fald, når vi forsøger at få user.address.street, og brugeren tilfældigvis ikke har en adresse, får vi en fejl:
Det er det forventede resultat. JavaScript fungerer sådan. Da user.address er undefined, mislykkes et forsøg på at få user.address.street med en fejl.
I mange praktiske tilfælde foretrækker vi at få undefined i stedet for en fejl her (betydende “ingen gade”).
…og et andet eksempel. I webudvikling kan vi få et objekt, der svarer til et websideelement ved hjælp af et specielt metodekald, såsom document.querySelector('.elem'), og det returnerer null, når der ikke er et sådant element.
Hvis elementet ikke findes, får vi en fejl, når vi forsøger at få adgang til .innerHTML-egenskaben af null. Og i nogle tilfælde, når fraværet af elementet er normalt, vil vi gerne undgå fejlen og blot acceptere html = null som resultatet.
Hvordan kan vi gøre dette?
Den oplagte løsning ville være at tjekke værdien ved hjælp af if eller den betingede operator ?, før vi får adgang til dens egenskab, sådan her:
let user = {};
alert(user.address ? user.address.street : undefined);
Det virker, der er ingen fejl… Men det er ret upraktisk. Som du kan se, optræder "user.address" to gange i koden.
Her er hvordan det samme ville se ud for document.querySelector:
Vi kan se, at element-søgningen document.querySelector('.elem') faktisk kaldes to gange her. Ikke godt.
For mere dybt indlejrede egenskaber bliver det endnu grimmere, da flere gentagelser er nødvendige.
F.eks. lad os få user.address.street.name på en lignende måde.
let user = {}; // user har ingen adresse
alert(user.address ? user.address.street ? user.address.street.name : null : null);
Det er skrækkeligt!. Flere kan endda have problemer med bare at forstå sådan kode.
Der er en lidt bedre måde at skrive det på ved hjælp af &&-operatoren:
At “AND’e” hele stien til egenskaben sikrer, at alle komponenter eksisterer (hvis ikke, stopper evalueringen), men det er heller ikke ideelt.
Som du kan se, optræder egenskabsnavne stadig flere gange i koden. F.eks. i koden ovenfor optræder user.address tre gange.
Derfor blev den valgfrie kædning ?. tilføjet til sproget. For at løse dette problem én gang for alle!
Valgfri kædning
Den valgfrie kædning ?. stopper evalueringen, hvis værdien før ?. er undefined eller null og returnerer undefined.
Fremover i denne artikel, for korthedens skyld, vil vi sige, at noget “eksisterer”, hvis det ikke er null og ikke undefined.
Med andre ord, value?.prop:
- fungerer som
value.prop, hvisvalueeksisterer, - ellers (når
valueerundefined/null) returnerer detundefined.
Her er den sikre måde at få adgang til user.address.street ved hjælp af ?.:
Koden er kort og ren, der er ingen duplikation overhovedet.
Her er et eksempel med document.querySelector:
At læse adressen med user?.address fungerer selvom user objektet ikke eksisterer:
Bemærk: ?.-syntaksen gør værdien før den valgfri, men ikke videre.
F.eks. i user?.address.street.name tillader ?. at user sikkert kan være null/undefined (og returnerer undefined i det tilfælde), men det gælder kun for user. Yderligere egenskaber tilgås på en almindelig måde. Hvis vi vil have nogle af dem til at være valgfrie, skal vi erstatte flere . med ?..
Vi bør kun bruge ?. der, hvor det er i orden, at noget ikke eksisterer.
For eksempel, hvis vores kodes logik kræver at user objektet eksisterer, men address er valgfri, så bør vi skrive user.address?.street, men ikke user?.address?.street.
På den måde, hvis user tilfældigvis er undefined, vil vi se en programmeringsfejl om det og rette det. Ellers, hvis vi overbruger ?., kan kodefejl blive tavse, hvor det ikke er passende, og blive sværere at debugge.
?. skal være deklareretKortslutning (Short-circuiting)
Som nævnt tidligere stopper ?. straks (“kortslutter”) evalueringen, hvis venstredelen ikke eksisterer.
Så hvis der er yderligere funktionskald eller operationer til højre for ?., vil de ikke blive udført.
For eksempel:
Andre varianter: ?.(), ?.[]
Den valgfrie kædning ?. er ikke en operator, men en særlig syntaks, der også fungerer med funktioner og firkantede parenteser.
For eksempel bruges ?.() til at kalde en funktion, der måske ikke eksisterer.
I koden nedenfor har nogle af vores brugere admin-metoden, og nogle har ikke:
Her bruger vi i begge linjer først punktum (userAdmin.admin) til at få admin-egenskaben, fordi vi antager, at user-objektet eksisterer, så det er sikkert at læse fra det.
Derefter tjekker ?.() venstredelen: hvis admin-funktionen findes, så kører den (det gælder for userAdmin). Ellers (for userGuest) stopper evalueringen uden fejl.
?.[]-syntaksen fungerer også, hvis vi gerne vil bruge firkantede parenteser [] til at få adgang til egenskaber i stedet for punktum .. Ligesom i de tidligere tilfælde tillader det at læse en egenskab sikkert fra et objekt, der måske ikke eksisterer.
Vi kan også bruge ?. med delete:
?. til sikker læsning og sletning, men ikke skrivningOpsummering
Den valgfrie kædning ?.-syntaks har tre former:
obj?.prop– returnererobj.prophvisobjeksisterer, ellersundefined.obj?.[prop]– returnererobj[prop]hvisobjeksisterer, ellersundefined.obj.method?.()– kalderobj.method()hvisobj.methodeksisterer, ellers returnererundefined.
Som vi kan se, er alle tre former enkle og ligetil at bruge. ?. tjekker venstredelen for null/undefined og tillader evalueringen at fortsætte, hvis det ikke er tilfældet.
En kæde af ?. tillader sikker adgang til indlejrede egenskaber.
Vi bør dog anvende ?. med omtanke, kun hvor det er acceptabelt ifølge vores kodelogik, at venstredelen ikke eksisterer. Så det ikke skjuler programmeringsfejl for os, hvis de opstår.