javascript - NULL-sikker egenskapsaksesjon og betinget tildeling i EcmaScript 6+
Finnes det en operator som vil gjøre det mulig å uttrykke følgende logikk (på linje 4) mer konsist?
const query = succeed => (succeed? {value: 4} : undefined);
let value = 3;
for (let x of [true, false]) {
try { value = query(x).value; } catch {} // <-- Don´t assign if no .value
}
console.log(value); Utdataene er 4. Hvis det ikke finnes noe .value-felt i responsen, vil jeg beholde den gamle value/ikke at tildelingen skal utføres.
Notater :
- Hvis
value=query(x)?.valueble brukt, ville det tildeleundefinedtilvalue - Det finnes også operatoren
??=, men den er ikke nyttig her,value ??= ...vil bare tilordne hvisvaluefor øyeblikket ernull/undefined - I CoffeeScript,
value=query(x).value if query(x)?.value?oppnår ønsket oppførsel utentry/catch, selv om det er repetitivt value=query(x)?.value ?? valuefungerer, men er ikke betinget tildeling, tildelingen skjer fortsatt. Hvis vi hadde satt enObjects egenskap, ville setter-metoden blitt kalt unødvendig. Det er også repetitivt- Denne logikken kan ikke abstrakteres til en funksjon, f.eks.
value=smart(query(x), "value"), tildelingen kan ikke gjøres betinget på den måten
Nøkkelord?
null-propagasjon, eksistensoperator
Svar #1
I noen år nå har det rett og slett vært
a?.b?.c
a?.b?.c ?? "default"
Sjekk «Can I Use» for kompatibilitet: https://caniuse.com/mdn-javascript_operators_optional_chaining,mdn-javascript_operators_nullish_coalescing
Oppdatering (2022-01-13): Ser ut som folk fortsatt finner dette, her er den nåværende historien:
- Valgfri kjeding er nå inkludert i spesifikasjonen (ES2020) og støttes av alle moderne nettlesere, mer i det arkiverte forslaget: https://github.com/tc39/proposal-optional-chaining
- babel-preset-env: Hvis du trenger å støtte eldre miljøer som ikke har det, er dette sannsynligvis det du vil ha https://babeljs.io/docs/en/babel-preset-env
- Babel v7-plugin: https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining
Oppdatering (2017-08-01): Hvis du vil bruke en offisiell plugin, kan du prøve alfa-versjonen av Babel 7 med den nye transformasjonen. Din erfaring kan variere
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
Original:
En funksjon som oppnår det er for øyeblikket i fase 1: Valgfri kjedning.
https://github.com/tc39/proposal-optional-chaining
Hvis du vil bruke det i dag, finnes det en Babel-plugin som gjør det.
https://github.com/davidyaha/ecmascript-optionals-proposal
Svar #2
Det er ikke like fint som ?. operatoren, men for å oppnå et lignende resultat kan du gjøre:
user && user.address && user.address.postcode
Siden null og undefined begge er falske verdier (se denne referansen), blir egenskapen etter &&-operatøren kun aksessert hvis den foregående ikke er null eller undefined.
Alternativt kunne du skrive en funksjon som dette:
function _try(func, fallbackValue) {
try {
var value = func();
return (value === null || value === undefined) ? fallbackValue : value;
} catch (e) {
return fallbackValue;
}
}
Bruk:
_try(() => user.address.postcode) // return postcode or undefined
Eller, med en tilbakefallsverdi:
_try(() => user.address.postcode, "none") // return postcode or a custom string
Svar #3
2020-løsning, ?. og ??
Du kan nå direkte bruke ?. (Valgfri kjeding) inline for å trygt teste om noe eksisterer. Alle moderne nettlesere støtter det.
?? (Nullish Coalescing) kan brukes for å sette en standardverdi hvis den er undefined eller null.
aThing = possiblyNull ?? aThing
aThing = a?.b?.c ?? possiblyNullFallback ?? aThing
Hvis en eiendom eksisterer, går ?. videre til neste sjekk, eller returnerer den gyldige verdien. Enhver feil vil umiddelbart korteslutte og returnere undefined.
const example = {a: ["first", {b:3}, false]}
example?.a // ["first", {b:3}, false]
example?.b // undefined
example?.a?.[0] // "first"
example?.a?.[1]?.a // undefined
example?.a?.[1]?.b // 3
domElement?.parentElement?.children?.[3]?.nextElementSibling
null?.() // undefined
validFunction?.() // result
(() => {return 1})?.() // 1
For å sikre en forhåndsdefinert verdi, kan du bruke ??. Hvis du trenger den første sannhet-verdien, kan du bruke ||.
example?.c ?? "c" // "c"
example?.c || "c" // "c"
example?.a?.[2] ?? 2 // false
example?.a?.[2] || 2 // 2
Hvis du ikke sjekker en sak, må venstresidens egenskap eksistere. Hvis ikke, vil det kaste en unntak.
example?.First // undefined
example?.First.Second // Uncaught TypeError: Cannot read property 'Second' of undefined
?. Nettleserstøtte - 92 %, nov 2021
?? Nettleserstøtte - 92%
Mozilla-dokumentasjon
--
Logisk null-tilordning, 2020+ løsning
Nye operatorer blir for øyeblikket lagt til i nettleserne, ??=, ||= og &&=. De gjør ikke helt det du ser etter, men kan føre til samme resultat avhengig av hva målet med koden din er.
MERK: Disse er ikke vanlige i offentlige nettleserversjoner ennå, men Babel bør transpile godt. Vil oppdatere etter hvert som tilgjengeligheten endres.
??= sjekker om venstre side er udefinert eller null, og stopper hvis den allerede er definert. Hvis ikke, blir venstre side tildelt høyre side sin verdi. ||= og &&= er liknende, men basert på || og && operatorene.
Grunnleggende eksempler
let a // undefined
let b = null
let c = false
a ??= true // true
b ??= true // true
c ??= true // false
Objekt/Array-eksempler
let x = ["foo"]
let y = { foo: "fizz" }
x[0] ??= "bar" // "foo"
x[1] ??= "bar" // "bar"
y.foo ??= "buzz" // "fizz"
y.bar ??= "buzz" // "buzz"
x // Array [ "foo", "bar" ]
y // Object { foo: "fizz", bar: "buzz" }
Nettleserstøtte nov 2021 - 90%
Mozilla-dokumentasjon
Svar #4
Nei. Du kan bruke lodash#get eller noe sånt for dette i JavaScript.
Svar #5
Vaniljealternativ for sikker tilgang til egenskaper
(((a.b || {}).c || {}).d || {}).e
Den mest konsise betingede tildelingen ville sannsynligvis være denne
try { b = a.b.c.d.e } catch(e) {}
