JavaScript Ternary Operator vs. ||

17

Wcześniej przyglądałem się kodowi node.js i zauważyłem, że facet, który go napisał, wydaje się faworyzować następującą składnię:

var fn = function (param) {
    var paramWithDefault = null == param ? 'Default Value' : param;
}

Ponad to, co uważam za bardziej zwięzłe:

var fn = function (param) {
    var paramWithDefault = param || 'Default Value';
}

Zastanawiałem się, czy druga forma jest w rzeczywistości bardziej akceptowalną społecznie składnią JavaScript, widziałem ją na wolności więcej razy niż operator trójskładnikowy w tym celu.

Zauważam, że w pierwszym przykładzie używa podwójnej równości (nie potrójnej równości), co oznacza, że ​​będzie ona traktowana jako „niezdefiniowana” jako zero, co zmniejszyłoby jeden wpływ, o którym mogłem pomyśleć. Jednak czytałem w wielu miejscach, że == jest raczej złym operatorem w JavaScript (JSLint jest temu bardzo przeciwny, IIRC).

Ed James
źródło
2
Komentatorzy: komentarze mają na celu poszukiwanie wyjaśnień, a nie dłuższą dyskusję. Jeśli masz rozwiązanie, zostaw odpowiedź. Jeśli Twoje rozwiązanie jest już opublikowane, głosuj za nim. Jeśli chcesz omówić to pytanie z innymi, skorzystaj z czatu . Aby uzyskać więcej informacji, zobacz często zadawane pytania .

Odpowiedzi:

17

Ponieważ ten kod będzie przyjmował wartość „Wartość domyślna” za każdym razem, gdy podasz 0, „”, fałsz lub inną wartość fałszowania.

function fn(param) {
  var paramWithDefault = param || 'Default Value';
  return paramWithDefault;
}

Być może nie gryzie Cię w sposobie korzystania z tej konkretnej funkcji, ale jest to zły wzorzec, którego należy unikać, gdy zależy ci na przekazywaniu rzeczy takich jak puste ciągi znaków lub wartość logiczna.

Peter Smith
źródło
powinieneś używać zerowej koalescencji na obiekcie, a jeśli obiekt jest zdefiniowany, to nie zadziała. Może z wyjątkiem pustego ciągu.
Malfist
4
Porównanie zera jest dobrym punktem, który może być dość nieoczekiwany.
Ed James
1
+1 - ten problem właśnie dlatego Python (ostatecznie) dodał składnię „x if y else z”. Te semantyki dla operatorów logicznych są dość powszechne, a te same typowe błędy pojawiają się, ilekroć idiomy na nich polegają, wykonując pracę operatorów selekcji warunkowej.
Steve314
tylko nie zapomnij umieścić swoich konstrukcji w nawiasach, jeśli użyjesz ich razem z konkatenacją łańcuchów var txt = 'Hello, ' + (user_name||'User') + '!';, zadziała, ale bez nawiasów - dostaniesz undefined. jsfiddle.net/4mFAB/1
c69
7

To, czego naprawdę potrzebujesz, to zerowy operator koalescencyjny. Ale widząc, że javascript tak naprawdę go nie ma, programiści zwykle używają „||” stać na to.

Oba są jednak całkowicie uzasadnione. Dla tych, którzy nie rozumieją, czym jest operator koalescencji zerowej, operator trójskładnikowy jest prawdopodobnie bardziej zrozumiały.

Malfist
źródło
Innym powiązanym operatorem jest operator Icon, który pisał IIRC „else”. To rozpoznaje specjalny wynik „porażki” z pierwszego argumentu i używa drugiego argumentu w tym przypadku jako alternatywy. Chciałbym, żeby Python „x if y else z” został zaimplementowany przy użyciu dwóch oddzielnych operatorów - operatora asercji binarnej „if” i operatora „else” podobnego do ikony - przy czym te dwa operatory mogą być używane niezależnie. Jednak Icon nie obsługiwał tego stylu, robiąc coś dziwnego z względnymi operatorami.
Steve314,
@ Steve314: Python ma coś, czego chciałeś: oddzielny operator else [false-part, true-part]z osobnym operatorem if w [..][bool(condition)]połączeniu [false-part, true-part][bool(condition)]. Jeśli chcesz leniwego zachowania, możesz po prostu wyrazić prawdę i fałsz.
Lie Ryan,