Beispiel für einen ternären JavaScript-Operator mit Funktionen

91

Ich verwende jQuery 1.7.1

Ich fange gerade an, den ternären JavaScript-Operator zu verwenden, um einfache if / else-Anweisungen zu ersetzen. Ich habe das an mehreren Stellen erfolgreich gemacht. Ich war überrascht, als ich erfolgreich etwas anderes zum Laufen brachte, als ich sicher war, dass es nicht funktionieren würde, aber ich versuchte es trotzdem.

Hier ist die ursprüngliche Aussage:

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

Hier ist die gleiche Funktion mit dem ternären Operator:

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

Ich war überrascht, weil alle Beispiele, die ich sah, lediglich Variablen wie diese setzten:

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

Meine Frage ist, ob dies "normal" ist und ob es in den meisten JavaScript-Versionen funktioniert. Wo wird es scheitern? Gibt es andere weniger offensichtliche Verwendungszwecke dafür?

UPDATE - Danke für den "echten" Rat !!!

Ich benutze dies als meine Funktion:

function updateItem() {
    $this = $(this);
    $this.hasClass("IsChecked") ? removeItem($this) : addItem($this);
}
Evik James
quelle
Es ist normal und funktioniert einwandfrei. Im Allgemeinen ist die Lesbarkeit bei Verwendung von ternären Operatoren schwierig, aber in Ihrem Fall sieht es gut aus.
Selvakumar Arumugam
1
Hmm ... Sie könnten dies auch tun, da beide die gleichen Argumente akzeptieren (IsChecked ? removeItem : addItem)($this). Um Ihre Frage zu beantworten: Ja, dies ist normal und es ist nichts Falsches daran, ternäre Operatoren zu verwenden, solange sie die Wartbarkeit oder Lesbarkeit in einer Situation, in der dies erforderlich ist, nicht beeinträchtigen. jsfiddle.net/vsB3f
Kevin B
if($this.hasClass("IsChecked")) removeItem($this); else addItem($this)ist der richtige Weg. Der ternäre Operator ist nicht für Fälle wie diesen gedacht, sondern für Dinge wie foo(isChecked ? 'bar' : meow());(dh wenn Sie sich um den "Rückgabewert" dessen kümmern, was Sie in den then / else-Blöcken tun)
ThiefMaster
1
Überspringen Sie in Ihrem Beispiel die erste Zeile dafür: $(this).hasClass("IsChecked") ? removeItem($this) : addItem($this); Ich kann Ihren Code so verstehen, wie er in einer Zeile ist, sodass er meiner Faustregel entspricht (siehe Beitrag unten). Funktioniert bei mir.
Surreale Träume

Antworten:

189

Heh, in Ihrer Frage gibt es einige ziemlich aufregende Anwendungen der ternären Syntax. Ich mag den letzten am liebsten ...

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

Die Verwendung von ternary ist hier völlig unnötig - man könnte einfach schreiben

x = (1 < 2);

Ebenso wird das Bedingungselement einer ternären Anweisung immer als boolescher Wert ausgewertet. Daher können Sie Folgendes ausdrücken:

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

Einfach als:

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

Tatsächlich würde ich auch das entfernen IsChecked Provisorium Ihnen lässt:

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

Ob dies eine akzeptable Syntax ist, ist es sicher! Es ist eine großartige Möglichkeit, vier Codezeilen in eine zu reduzieren, ohne die Lesbarkeit zu beeinträchtigen. Der einzige Ratschlag, den ich Ihnen geben würde, ist zu vermeiden, mehrere ternäre Aussagen in derselben Zeile zu verschachteln (auf diese Weise liegt der Wahnsinn!).

JonnyReeves
quelle
Beachten Sie, dass Sie möglicherweise vermeiden möchten, Großbuchstaben in Klassennamen zu verwenden (IsChecked wird überprüft) stackoverflow.com/questions/1547986/…
Adrien Be
JS hat erstklassige Funktionen:($this.hasClass("isChecked") ? removeItem : addItem)($this)
ClojureMostly
22

Der ternäre Stil wird im Allgemeinen verwendet, um Platz zu sparen. Semantisch sind sie identisch. Ich bevorzuge die vollständige if / then / else-Syntax, weil ich die Lesbarkeit nicht opfern möchte - ich bin altmodisch und bevorzuge meine Zahnspange.

Das vollständige if / then / else-Format wird für so ziemlich alles verwendet. Es ist besonders beliebt, wenn Sie in jedem Zweig in größere Codeblöcke geraten, einen mehrfach verzweigten if / else-Baum oder mehrere else / ifs in einer langen Zeichenfolge haben.

Der ternäre Operator ist häufig, wenn Sie einer Variablen basierend auf einer einfachen Bedingung einen Wert zuweisen oder mehrere Entscheidungen mit sehr kurzen Ergebnissen treffen. Das von Ihnen zitierte Beispiel ist eigentlich nicht sinnvoll, da der Ausdruck ohne zusätzliche Logik zu einem der beiden Werte ausgewertet wird.

Gute Ideen:

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
{
    ...

Weniger gut:

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;
}

Eine wirklich grundlegende Faustregel - können Sie das Ganze auch oder besser in einer Zeile verstehen? Ternary ist in Ordnung. Andernfalls erweitern Sie es.

Surreale Träume
quelle
7

Das von Ihnen veröffentlichte Beispiel ist nicht besonders schwierig.

In einem ternären Operator wird das erste Argument (die Bedingung) ausgewertet und wenn das Ergebnis ist true , wird das zweite Argument ausgewertet und zurückgegeben, andernfalls wird das dritte ausgewertet und zurückgegeben. Jedes dieser Argumente kann ein beliebiger gültiger Codeblock sein, einschließlich Funktionsaufrufen.

Denk darüber so:

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

Könnte auch geschrieben werden als:

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

Dies ist vollkommen gültig, und diese Funktionen können beliebigen Code enthalten, unabhängig davon, ob es sich um die Rückgabe eines Werts handelt oder nicht. Darüber hinaus müssen die Ergebnisse der ternären Operation nichts zugewiesen werden, ebenso wie die Funktionsergebnisse nichts zugewiesen werden müssen:

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

Ersetzen Sie diese nun einfach durch beliebige Funktionen, und Sie haben so etwas wie Ihr Beispiel:

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

Jetzt braucht Ihr letztes Beispiel wirklich überhaupt kein Ternär, da es so geschrieben werden kann:

x = (1 < 2);  // x will be set to "true"
Jeff B.
quelle
6

Wenn Sie ternäre Operatoren verschachteln möchten, möchten Sie wahrscheinlich Folgendes tun:

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

Schreiben / Lesen ist viel effizienter als:

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

Wie bei jeder guten Programmierung macht Whitespace alles schön für Leute, die Ihren Code lesen müssen, nachdem Sie mit dem Projekt fertig sind.

Sam W.
quelle
6
Stimme überhaupt nicht mit deinem obigen Kommentar überein, dass verschachtelte ternäre Dateien einfacher zu lesen und zu debuggen sind. Persönlich würde ich lieber sehen, dass der verschachtelte else / if-Block entweder durch eine Nachschlagetabelle oder eine switch-Anweisung ersetzt wird.
JonnyReeves
@JonnyReeves stimmte zu - normalerweise wird die verschachtelte ternäre Syntax am besten verwendet, wenn verschiedene Bedingungen (z. B. Modulo von Zahlen )
überprüft werden
6

Ich möchte auch etwas von mir hinzufügen.

Eine andere mögliche Syntax zum Aufrufen von Funktionen mit dem ternären Operator wäre:

(condition ? fn1 : fn2)();

Es kann praktisch sein, wenn Sie beiden Funktionen dieselbe Liste von Parametern übergeben müssen, sodass Sie sie nur einmal schreiben müssen.

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

Sie können den ternären Operator auch mit Mitgliedsfunktionsnamen verwenden, was mir persönlich sehr gefällt, um Platz zu sparen:

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

oder

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

Ein anderes Beispiel:

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

Ich weiß, dass die Frage bereits beantwortet ist.

Aber lassen Sie mich hier einen Punkt hinzufügen. Dies ist nicht nur ein Fall von wahr oder falsch. Siehe unten:

var val="Do";

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

Wenn val Do oder Done ist, ist c 7, andernfalls ist es Null. In diesem Fall ist c 7.

Dies ist tatsächlich eine andere Perspektive dieses Operators.

Himanshu Tiwari
quelle