Przykład operatora trójskładnikowego JavaScript z funkcjami

91

Używam jQuery 1.7.1

Właśnie zaczynam używać operatora trójargumentowego JavaScript do zastępowania prostych instrukcji if / else. Zrobiłem to pomyślnie w kilku miejscach. Byłem zaskoczony, gdy udało mi się zrobić coś innego, kiedy myślałem, że na pewno nie, ale i tak próbowałem.

Oto oryginalne stwierdzenie:

function updateItem() {
    $this = $(this);
    var IsChecked = $this.hasClass("IsChecked");
    if (IsChecked == true){
        removeItem($this);
    } else {
        addItem($this);
    }
}

Oto ta sama funkcja wykorzystująca operator trójskładnikowy:

function updateItem() {
    $this = $(this);
    var IsChecked = $this.hasClass("IsChecked");
    (IsChecked == true) ? removeItem($this) : addItem($this);
}

Byłem zaskoczony, ponieważ wszystkie przykłady, które widziałem, były używane tylko do ustawiania takich zmiennych:

x = (1 < 2) ? true : false;

Moje pytanie brzmi, czy jest to „normalne” użycie i czy będzie działać w większości wersji JavaScript? Gdzie to się nie uda? Czy są inne, mniej oczywiste zastosowania?

AKTUALIZACJA - Dzięki za rady dotyczące „prawdziwego świata” !!!

Używam tego jako mojej funkcji:

function updateItem() {
    $this = $(this);
    $this.hasClass("IsChecked") ? removeItem($this) : addItem($this);
}
Evik James
źródło
Jest to normalne i będzie działać dobrze. Ogólnie, czytelność jest trudna przy korzystaniu z operatorów trójskładnikowych, ale w twoim przypadku wygląda dobrze.
Selvakumar Arumugam
1
Hmm ... możesz to również zrobić, ponieważ obaj akceptują te same argumenty (IsChecked ? removeItem : addItem)($this). Jednak odpowiadając na twoje pytanie, tak, jest to normalne i nie ma nic złego w używaniu operatorów trójskładnikowych, o ile nie zmniejszają one łatwości utrzymania lub czytelności w sytuacji, w której jest to potrzebne. jsfiddle.net/vsB3f
Kevin B
if($this.hasClass("IsChecked")) removeItem($this); else addItem($this)jest właściwą drogą. Operator trójargumentowy nie jest przeznaczony do takich przypadków, ale do rzeczy takich jak foo(isChecked ? 'bar' : meow());(tj. Kiedy zależy Ci na „wartości zwracanej” tego, co robisz w blokach then / else)
ThiefMaster
1
W twoim przykładzie pomiń pierwszą linię na korzyść tego: $(this).hasClass("IsChecked") ? removeItem($this) : addItem($this); Rozumiem twój kod w jednej linii, więc pasuje do mojej praktycznej zasady (patrz post poniżej). Pracuje dla mnie.
Surreal Dreams

Odpowiedzi:

189

Heh, w twoim pytaniu jest kilka całkiem ekscytujących zastosowań trójskładniowej składni; Ten ostatni lubię najbardziej ...

x = (1 < 2) ? true : false;

Użycie tutaj trójskładnika jest zupełnie niepotrzebne - można by po prostu napisać

x = (1 < 2);

Podobnie element warunkowy instrukcji trójskładnikowej jest zawsze oceniany jako wartość logiczna, dlatego można wyrazić:

(IsChecked == true) ? removeItem($this) : addItem($this);

Po prostu jak:

(IsChecked) ? removeItem($this) : addItem($this);

W rzeczywistości usunąłbym również IsCheckedtymczasowy, który pozostawia ci:

($this.hasClass("IsChecked")) ? removeItem($this) : addItem($this);

Jeśli chodzi o to, czy jest to dopuszczalna składnia, na pewno tak! To świetny sposób na zredukowanie czterech wierszy kodu w jeden bez wpływu na czytelność. Jedyna rada, jaką mógłbym wam dać, to unikanie zagnieżdżania wielu zdań trójskładnikowych w tej samej linii (w ten sposób leży szaleństwo!)

JonnyReeves
źródło
zauważ, że możesz chcieć uniknąć używania wielkich liter w nazwach klas (IsChecked staje się sprawdzany) stackoverflow.com/questions/1547986/ ...
Adrien Be
JS ma funkcje pierwszej klasy:($this.hasClass("isChecked") ? removeItem : addItem)($this)
Clojure Przeważnie
22

Styl trójskładnikowy jest zwykle używany, aby zaoszczędzić miejsce. Semantycznie są identyczne. Wolę korzystać z pełnej składni if ​​/ then / else, ponieważ nie lubię rezygnować z czytelności - jestem oldschoolowy i wolę swoje szelki.

Pełny format if / then / else jest używany do prawie wszystkiego. Jest to szczególnie popularne, jeśli w każdej gałęzi znajdziesz większe bloki kodu, masz rozgałęzione drzewo if / else lub wiele else / if w długim ciągu.

Operator trójargumentowy jest powszechny, gdy przypisujesz wartość do zmiennej na podstawie prostego warunku lub podejmujesz wiele decyzji z bardzo krótkimi wynikami. Przykład, który przytaczasz, w rzeczywistości nie ma sensu, ponieważ wyrażenie będzie obliczane na jedną z dwóch wartości bez dodatkowej logiki.

Dobre pomysły:

this > that ? alert(this) : alert(that);  //nice and short, little loss of meaning

if(expression)  //longer blocks but organized and can be grasped by humans
{
    //35 lines of code here
}
else if (something_else)
{
    //40 more lines here
}
else if (another_one)  /etc, etc
{
    ...

Mniej dobre:

this > that ? testFucntion() ? thirdFunction() ? imlost() : whathappuh() : lostinsyntax() : thisisprobablybrokennow() ? //I'm lost in my own (awful) example by now.
//Not complete... or for average humans to read.

if(this != that)  //Ternary would be done by now
{
    x = this;
}
else
}
    x = this + 2;
}

Naprawdę podstawowa zasada - można zrozumieć całość równie dobrze lub lepiej w jednej linii? Ternary jest OK. W przeciwnym razie rozwiń go.

Surreal Dreams
źródło
7

Nie ma nic szczególnie trudnego w opublikowanym przykładzie.

W operatorze trójargumentowym pierwszy argument (warunkowy) jest oceniany, a jeśli wynik to true, drugi argument jest oceniany i zwracany, w przeciwnym razie trzeci jest oceniany i zwracany. Każdy z tych argumentów może być dowolnym prawidłowym blokiem kodu, w tym wywołaniami funkcji.

Pomyśl o tym w ten sposób:

var x = (1 < 2) ? true : false;

Można też zapisać jako:

var x = (1 < 2) ? getTrueValue() : getFalseValue();

Jest to całkowicie poprawne, a funkcje te mogą zawierać dowolny kod, niezależnie od tego, czy jest związany ze zwracaniem wartości, czy nie. Dodatkowo wyniki operacji trójskładnikowej nie muszą być do niczego przypisywane, podobnie jak wyniki funkcji nie muszą być do niczego przypisywane:

(1 < 2) ? getTrueValue() : getFalseValue();

Teraz po prostu zastąp je dowolnymi dowolnymi funkcjami, a zostanie Ci coś podobnego do twojego przykładu:

(1 < 2) ? removeItem($this) : addItem($this);

Teraz twój ostatni przykład naprawdę nie potrzebuje trójskładnika, ponieważ można go zapisać w ten sposób:

x = (1 < 2);  // x will be set to "true"
Jeff B.
źródło
7

Chciałbym też coś dodać ode mnie.

Inną możliwą składnią do wywoływania funkcji z operatorem trójargumentowym byłaby:

(condition ? fn1 : fn2)();

Może to być przydatne, jeśli musisz przekazać tę samą listę parametrów do obu funkcji, więc musisz je zapisać tylko raz.

(condition ? fn1 : fn2)(arg1, arg2, arg3, arg4, arg5);

Możesz użyć operatora trójskładnikowego nawet z nazwami funkcji składowych, które osobiście bardzo lubię, aby zaoszczędzić miejsce:

$('.some-element')[showThisElement ? 'addClass' : 'removeClass']('visible');

lub

$('.some-element')[(showThisElement ? 'add' : 'remove') + 'Class']('visible');

Inny przykład:

var addToEnd = true; //or false
var list = [1,2,3,4];
list[addToEnd ? 'push' : 'unshift'](5);
Bartłomiej Zalewski
źródło
6

Jeśli zamierzasz zagnieżdżać operatory trójskładnikowe, uważam, że chciałbyś zrobić coś takiego:

   var audience = (countrycode == 'eu') ? 'audienceEU' :
                  (countrycode == 'jp') ? 'audienceJP' :
                  (countrycode == 'cn') ? 'audienceCN' :
                  'audienceUS';

Pisanie / czytanie jest o wiele bardziej wydajne niż:

var audience = 'audienceUS';
if countrycode == 'eu' {
   audience = 'audienceEU';
} else if countrycode == 'jp' {
   audience = 'audienceJP';
} else if countrycode == 'cn' {
   audience = 'audienceCN';
}

Podobnie jak w przypadku każdego dobrego programowania, białe znaki sprawiają, że wszystko jest przyjemne dla ludzi, którzy muszą czytać Twój kod po zakończeniu projektu.

Sam W.
źródło
6
Zdecydowanie nie zgadzam się z powyższym komentarzem, że zagnieżdżona trójka jest łatwiejsza do odczytania i debugowania. Osobiście wolałbym, aby zagnieżdżony blok else / if został zastąpiony tabelą odnośników lub instrukcją switch.
JonnyReeves,
@JonnyReeves zgodził się - zwykle zagnieżdżona składnia trójskładnikowa jest najlepiej używana do sprawdzania różnych warunków (np. Modulo liczb )
AlexFoxGill
2

Wiem, że na pytanie już udzielono odpowiedzi.

Ale pozwolę sobie dodać tutaj jedną kwestię. Nie dotyczy to tylko prawdy lub fałszu. Zobacz poniżej:

var val="Do";

Var c= (val == "Do" || val == "Done")
          ? 7
          : 0

Tutaj, jeśli val to Do lub Done, to c będzie wynosić 7, w przeciwnym razie będzie równe zero. W tym przypadku c będzie równe 7.

To właściwie inna perspektywa tego operatora.

Himanshu Tiwari
źródło