Chciałbym utworzyć obiekt z członkiem dodanym warunkowo. Proste podejście to:
var a = {};
if (someCondition)
a.b = 5;
Teraz chciałbym napisać bardziej idiomatyczny kod. Próbuję:
a = {
b: (someCondition? 5 : undefined)
};
Ale teraz b
jest członkiem, a
którego wartość jest undefined
. To nie jest pożądany wynik.
Czy istnieje przydatne rozwiązanie?
Aktualizacja
Szukam rozwiązania, które mogłoby poradzić sobie z ogólną sprawą z udziałem kilku członków.
a = {
b: (conditionB? 5 : undefined),
c: (conditionC? 5 : undefined),
d: (conditionD? 5 : undefined),
e: (conditionE? 5 : undefined),
f: (conditionF? 5 : undefined),
g: (conditionG? 5 : undefined),
};
javascript
Viebel
źródło
źródło
a.b
, pobieraniea.b
iundefined
tak zwróci .in
operator jest używany.Odpowiedzi:
W czystym JavaScript nie mogę wymyślić nic bardziej idiomatycznego niż twój pierwszy fragment kodu.
Jeśli jednak użycie biblioteki jQuery nie wchodzi w rachubę, to $ .extend () powinno spełniać twoje wymagania, ponieważ, jak wynika z dokumentacji:
Dlatego możesz napisać:
I uzyskaj oczekiwane wyniki (jeśli
conditionB
takfalse
, tob
nie będą istnieć wa
).źródło
Myślę, że @InspiredJW zrobił to z ES5 i jak zauważył @trincot, użycie es6 jest lepszym podejściem. Ale możemy dodać nieco więcej cukru, używając operatora spreadu i logicznej ORAZ oceny zwarcia:
źródło
Null/Undefined Are Ignored
, że niefalse
jest ignorowane. Transpilatorzy mogą obecnie na to pozwolić, ale czy jest to zgodne? Poniższe powinny być,{...someCondition ? {b: 5} : null}
ale nie są tak zwarte.Object.assign
i ma niższy priorytet niż operator &&. Ignoruje wartość bez właściwości (boolean, null, undefined, number) i dodaje wszystkie właściwości obiektu po...
miejscu. pamiętaj, że&&
operator zwraca poprawną wartość, jeśli true lub false w przeciwnym razie. więc jeślisomeCondition
jest prawdą,{b : 5}
zostanie przekazany do...
operatora, co spowoduje dodanie właściwościb
doa
wartości5
. jestsomeCondition
fałszywe,false
zostanie przekazane...
operatorowi. w wyniku czego nic nie zostało dodane. to sprytne. Kocham to.Z EcmaScript2015 możesz używać
Object.assign
:Pokaż fragment kodu
Kilka uwag:
Object.assign
modyfikuje pierwszy argument na miejscu, ale zwraca również zaktualizowany obiekt: dzięki czemu można użyć tej metody w większym wyrażeniu, które dalej manipuluje obiektem.null
ciebie możesz przejśćundefined
lub{}
, z tym samym rezultatem. Możesz nawet podać0
zamiast tego, ponieważ pierwotne wartości są opakowane iNumber
nie mają własnych właściwości, które można wyliczyć .Jeszcze bardziej zwięzłe
Biorąc drugi punkt dalej, można go skrócić następująco (jak @Jamie wskazał), jako wartości falsy nie mają własnych właściwości przeliczalny (
false
,0
,NaN
,null
,undefined
,''
, z wyjątkiemdocument.all
):Pokaż fragment kodu
źródło
Demo na żywo:
źródło
Używanie składni rozszerzonej z wartością logiczną (jak sugerowano tutaj) nie jest prawidłową składnią. Spread można stosować tylko z iterami .
Proponuję następujące:
źródło
{...false}
{...false}
jest poprawną składnią.CopyDataProperties
jest wykonywana (false
w tym przypadku). Obejmuje to boksowanie prymitywów (sekcje 7.3.23, 7.1.13). Link do MDN wymienia ten „wyjątek” w nawiasach.A co z korzystaniem z Ulepszonych właściwości obiektu i ustawianie właściwości tylko wtedy, gdy jest to zgodne z prawdą, np .:
Jeśli więc warunek nie jest spełniony, nie tworzy preferowanej właściwości i dlatego możesz ją odrzucić. Zobacz: http://es6-features.org/#ComputedPropertyNames
AKTUALIZACJA: Jeszcze lepiej jest podążać za podejściem Axela Rauschmayera w jego blogu na temat warunkowego dodawania wpisów do literałów obiektów i tablic ( http://2ality.com/2017/04/conditional-literal-entries.html ):
Bardzo mi pomogło.
źródło
false
klucz. Na przykład{[true && 'a']: 17, [false && 'b']: 42}
jest{a:17, false: 42}
...isConditionTrue() && { propertyName: 'propertyValue' }
bardziej uproszczony,
źródło
Jeśli celem jest, aby obiekt wyglądał na niezależny i znajdował się w jednym zestawie nawiasów klamrowych, możesz spróbować:
źródło
Jeśli chcesz zrobić to po stronie serwera (bez jquery), możesz użyć lodash 4.3.0:
I to działa przy użyciu lodash 3.10.1
źródło
Mam nadzieję, że jest to bardzo skuteczny sposób dodawania wpisu na podstawie warunku. Aby uzyskać więcej informacji na temat warunkowego dodawania wpisów do literałów obiektowych.
źródło
[...condition?'':['item']]
to doda element ciągu do tablicyOd dawna już na nie odpowiedziano, ale patrząc na inne pomysły wpadłem na interesującą pochodną:
Przypisz niezdefiniowane wartości do tej samej właściwości, a następnie usuń ją
Utwórz obiekt za pomocą anonimowego konstruktora i zawsze przypisuj niezdefiniowane elementy do tego samego elementu zastępczego, który usuwasz na samym końcu. To da ci jedną linię (mam nadzieję, że nie jest zbyt złożona) na członka + 1 dodatkową linię na końcu.
źródło
Możesz dodać wszystkie swoje niezdefiniowane wartości bez warunków, a następnie użyć ich
JSON.stringify
do usunięcia wszystkich:źródło
Zrobiłbym to
Edytowane z jedną wersją kodu linii
źródło
a = undefined
return { b: undefined };
return {};
welse
częścia = condition ? {b:5} : undefined;
Korzystając z biblioteki lodash, możesz użyć _.omitBy
Jest to przydatne, gdy masz opcjonalne żądania
źródło
Myślę, że twoje pierwsze podejście do warunkowego dodawania członków jest w porządku. Naprawdę nie zgadzam się z tym, że nie chcę mieć członka
b
oa
wartościundefined
. Wystarczy dodaćundefined
czek z użyciemfor
pętli zin
operatorem. Ale w każdym razie możesz łatwo napisać funkcję do odfiltrowywaniaundefined
członków.Możesz także użyć
delete
operatora do edycji obiektu na miejscu.źródło
Zawiń w obiekt
Coś takiego jest nieco czystsze
Zawiń w tablicę
Lub jeśli chcesz skorzystać z metody Jamiego Hilla i mieć bardzo długą listę warunków, musisz napisać
...
składnię wiele razy. Aby było trochę czystsze, możesz po prostu owinąć je w tablicę, a następnie użyć,reduce()
aby zwrócić je jako pojedynczy obiekt.Lub używając
map()
funkcjiźródło
To najbardziej zwięzłe rozwiązanie, jakie mogę wymyślić:
źródło
Korzystając z biblioteki lodash, możesz użyć _.merge
false
& warunek C totrue
, toa = { c: 5 }
true
, toa = { b: 4, c: 5 }
false
, toa = {}
źródło
lodash@^4.0.0
.undefined
są uwzględnione w moim przypadku.