Czy null
w ES6 (ES2015 / JavaScript.next / Harmony) istnieje operator -safe dostępu do właściwości (propagacja / istnienie wartości null), na przykład ?.
w CoffeeScript ? A może planowane jest na ES7?
var aThing = getSomething()
...
aThing = possiblyNull?.thing
Będzie to mniej więcej tak:
if (possiblyNull != null) aThing = possiblyNull.thing
W idealnym przypadku rozwiązanie nie powinno przypisywać (nawet undefined
) warunku, aThing
jeśli possiblyNull
jestnull
if( obj?.nested?.property?.value )
zamiastif( obj && obj.nested && obj.nested.property && obj.nested.property.value )
var appConfig = loadConfig(config, process.env); connect(appConfig.database);
doconnect(config)
. Można przekazać wiele prostsze do obiektuconnect
zamiast przechodząc całyconfig
obiekt, można użyćconf.username
,conf.password
zamiast próbować coś podobnegoconfig[process.env]?.database?.username
,config[process.env]?.database?.password
. Odniesienie: Prawo Demeter .loadConfig
powyższym przykładzie), możesz przyjąć założenia dotyczące istnienia właściwości i pominąć sprawdzanie wartości null w niezliczonych obszarach aplikacji.Odpowiedzi:
Aktualizacja (2020-01-31): Wygląda na to, że ludzie wciąż to odkrywają, oto aktualna historia:
Aktualizacja (2017-08-01): Jeśli chcesz użyć oficjalnej wtyczki, możesz wypróbować wersję alfa Babel 7 z nową transformacją. Twój przebieg może się różnić
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
Oryginał :
Funkcja, która spełnia to, co jest obecnie na etapie 1: Opcjonalne łączenie w łańcuch.
https://github.com/tc39/proposal-optional-chaining
Jeśli chcesz go dzisiaj używać, dostępna jest wtyczka Babel, która to umożliwia.
https://github.com/davidyaha/ecmascript-optionals-proposal
źródło
street = user.address?.street
ustawiłby sięstreet
w każdym przypadku?Street
Myślę, że zostanie przydzielonyundefined
. Ale przynajmniej nie rzuciłby się na próbę dostępu do właściwości na undefined.=
, wygląda na to, że nie jest to obecnie obsługiwane w oficjalnej specyfikacji. github.com/tc39/proposal-optional-chaining#not-supportedTo nie jest tak ładne jak?. operator, ale aby osiągnąć podobny wynik, możesz zrobić:
Ponieważ obie wartości
null
iundefined
są wartościami fałszywymi ( zobacz to odniesienie ), dostęp do właściwości po&&
operatorze jest możliwy tylko wtedy, gdy w poprzedniku nie ma wartości null lub undefined.Alternatywnie możesz napisać taką funkcję:
Stosowanie:
Lub z wartością zastępczą:
źródło
!(user && user.address && user.address.postcode)
:)foo && foo.bar && foo.bar.quux ...
w dużej bazie kodów jest to brzydkie i powoduje wiele komplikacji, których lepiej byłoby unikać._get<T>(func: () => T, fallbackValue?: T) :T
user.address.postcode
jest niezdefiniowane,_try(() => user.address.postcode, "")
zwróciundefined
zamiast""
. Więc kod_try(() => user.address.postcode, "").length
zgłosi wyjątek.Nie. Możesz użyć lodash # get lub czegoś podobnego do tego w JavaScript.
źródło
lodash.get
jest nieco inny, ponieważ oczywiście nie może wykonać przypisania warunkowego.Alternatywa waniliowa zapewniająca bezpieczny dostęp do nieruchomości
Prawdopodobnie najbardziej zwięzłe przypisanie warunkowe byłoby takie
źródło
possiblyNull
nie jest zdefiniowany /null
?||=
(((a.b || {}).c || {}).d || {}).e
. Ale bardziej precyzyjne byłoby((((a || {}).b || {}).c || {}).d || {}).e
Nie, w ES6 nie ma operatora propagacji zerowej. Będziesz musiał zastosować jeden ze znanych wzorów .
Możesz jednak użyć destrukturyzacji:Jest wiele dyskusji (np. Ta ) na temat dodania takiego operatora w ES7, ale żadna tak naprawdę się nie rozpoczęła.
źródło
aThing = possiblyNull.thing
null
. Musiałbyś podać wartość domyślną, podobną do tego wzorca, ale z bardziej zagmatwaną składnią.Przechodzenie przez listę tutaj , nie ma obecnie propozycja, aby dodać bezpieczne przechodzenie do ECMAScript. Więc nie tylko nie ma na to fajnego sposobu, ale nie zostanie dodany w przewidywalnej przyszłości.
źródło
źródło
Opcjonalne
?.
łączenie łańcuchowe i zerowe łączenie??
Możesz teraz bezpośrednio użyć
?.
inline, aby bezpiecznie przetestować istnienie. Obsługują ją wszystkie nowoczesne przeglądarki.??
można użyć do ustawienia wartości domyślnej, jeśli jest ona niezdefiniowana lub zerowa.Jeśli właściwość istnieje,
?.
przechodzi do następnego sprawdzenia lub zwraca prawidłową wartość. Każda awaria spowoduje natychmiastowe zwarcie i powrótundefined
.Aby zapewnić domyślną zdefiniowaną wartość, możesz użyć
??
. Jeśli potrzebujesz pierwszej prawdziwej wartości, możesz użyć||
.Jeśli nie zaznaczysz przypadku, właściwość po lewej stronie musi istnieć. Jeśli nie, zgłosi wyjątek.
?.
Obsługa przeglądarek - 78%, lipiec 2020 r??
Obsługa przeglądarek - 78%Dokumentacja Mozilli
-
Logiczne przypisanie zerowe, rozwiązanie 2020+
Obecnie do przeglądarek dodaje się nowych operatorów
??=
,||=
i&&=
. Nie robią dokładnie tego, czego szukasz, ale mogą prowadzić do tego samego wyniku w zależności od celu twojego kodu.??=
sprawdza, czy lewa strona jest niezdefiniowana lub zerowa, przerywając, jeśli jest już zdefiniowana. Jeśli nie, lewej stronie przypisywana jest wartość prawej strony.||=
i&&=
są podobne, ale oparte na operatorach||
i&&
.Podstawowe przykłady
Przykłady obiektów / tablic
Wsparcie przeglądarek lipiec 2020 - 0,03%
Dokumentacja Mozilli
źródło
?.
i??
oraz szczegółowe nadchodzące rozwiązanie, które może działać w Twojej sytuacji. Prawdopodobnie najlepsze obecne rozwiązanie to po prostu zrobićaThing = possiblyNull?.thing ?? aThing
Bezpieczna metoda głębokiego pobierania wydaje się być naturalnym rozwiązaniem dla underscore.js, ale problemem jest unikanie programowania ciągów. Modyfikowanie odpowiedzi @ Felipe, aby uniknąć programowania ciągów (lub przynajmniej odsuwa przypadki brzegowe z powrotem do dzwoniącego):
Przykład:
źródło
_.get(obj, array_or_dotstring)
obj.a.b.c
porównaniu zobj['a']['b']['c']
keys
?Wiem, że jest to pytanie JavaScript, ale myślę, że Ruby obsługuje to na wszystkie wymagane sposoby, więc myślę, że jest to odpowiedni punkt odniesienia.
.&
,try
i && mają swoje mocne strony i potencjalne pułapki. Świetny przegląd tych opcji tutaj: http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/TLDR; Konkluzja rubinów jest taka, że
dig
jest zarówno przyjemniejsza dla oczu, jak i silniejsza gwarancja, że wartość lubnull
zostanie przypisana.Oto prosta implementacja w TypeScript:
Może to być używane dla dowolnej głębokości zagnieżdżania i obsługuje funkcje.
try
Podejście jest równie miłe czytać w JS, jak pokazano w poprzednich odpowiedziach. Nie wymaga też zapętlenia, co jest jedną z wad tej implementacji.źródło
Pomyślałem, że to pytanie wymaga trochę odświeżenia na rok 2018. Można to zrobić ładnie bez użycia bibliotek
Object.defineProperty()
i można z niego korzystać w następujący sposób:Uważam to za bezpieczne (i js-etyczne) ze względu na definicje
writeable
ienumerable
obecnie dostępne dladefineProperty
metodyObject
, jak udokumentowano w MDNdefinicja funkcji poniżej:
Przygotowałem plik jsBin z wyjścia konsoli do wykazania tego. Zwróć uwagę, że w wersji jsBin dodałem również niestandardowy wyjątek dla pustych wartości. Jest to opcjonalne, więc pominąłem to minimum powyżej.
Mile widziane ulepszenia
źródło