Exemple d'opérateur ternaire JavaScript avec fonctions

91

J'utilise jQuery 1.7.1

Je commence tout juste à utiliser l'opérateur ternaire JavaScript pour remplacer de simples instructions if / else. Je l'ai fait avec succès à plusieurs endroits. J'ai été surpris quand j'ai réussi à faire fonctionner quelque chose d'autre alors que je pensais avec certitude que ce ne serait pas le cas, mais j'ai quand même essayé.

Voici la déclaration originale:

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

Voici la même fonction utilisant l'opérateur ternaire:

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

J'ai été surpris car tous les exemples que j'ai vus utilisés ne faisaient que définir des variables comme celle-ci:

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

Ma question est de savoir si c'est une utilisation "normale" et cela fonctionnera-t-il dans la plupart des versions de JavaScript? Où échouera-t-il? Y a-t-il d'autres utilisations moins évidentes?

MISE À JOUR - Merci pour les conseils "du monde réel" !!!

J'utilise ceci comme ma fonction:

function updateItem() {
    $this = $(this);
    $this.hasClass("IsChecked") ? removeItem($this) : addItem($this);
}
Evik James
la source
C'est normal et cela fonctionnera très bien. En général, la lisibilité est difficile lorsque vous utilisez des opérateurs ternaires, mais dans votre cas, cela semble très bien.
Selvakumar Arumugam
1
Hmm ... vous pouvez également le faire car ils acceptent tous les deux les mêmes arguments (IsChecked ? removeItem : addItem)($this). Cependant, pour répondre à votre question, oui, c'est normal et il n'y a rien de mal à utiliser des opérateurs ternaires tant qu'ils ne nuisent pas à la maintenabilité ou à la lisibilité dans une situation où cela est nécessaire. jsfiddle.net/vsB3f
Kevin B
if($this.hasClass("IsChecked")) removeItem($this); else addItem($this)est la bonne manière. L'opérateur ternaire n'est pas destiné à des cas comme celui-ci mais à des choses comme foo(isChecked ? 'bar' : meow());(c'est-à-dire lorsque vous vous souciez de la "valeur de retour" de tout ce que vous faites dans les blocs then / else)
ThiefMaster
1
Dans votre exemple, sautez la première ligne en faveur de ceci: $(this).hasClass("IsChecked") ? removeItem($this) : addItem($this); je peux comprendre votre code tel quel sur une ligne, donc il correspond à ma règle de base (voir l'article ci-dessous). Travaille pour moi.
Surreal Dreams

Réponses:

189

Heh, il y a des utilisations assez intéressantes de la syntaxe ternaire dans votre question; J'aime le dernier le meilleur ...

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

L'utilisation de ternaire ici est totalement inutile - vous pouvez simplement écrire

x = (1 < 2);

De même, l'élément condition d'une instruction ternaire est toujours évalué comme une valeur booléenne, vous pouvez donc exprimer:

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

Simplement comme:

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

En fait, je supprimerais également le IsCheckedtemporaire qui vous laisse avec:

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

Quant à savoir si cette syntaxe est acceptable, c'est sûr! C'est un excellent moyen de réduire quatre lignes de code en une seule sans affecter la lisibilité. Le seul conseil que je vous donnerais est d'éviter d'imbriquer plusieurs énoncés ternaires sur la même ligne (c'est la folie!)

JonnyReeves
la source
notez que vous voudrez peut-être éviter d'utiliser des majuscules dans les noms de classe (IsChecked devenant est vérifié) stackoverflow.com/questions/1547986/…
Adrien Be
JS a des fonctions de première classe:($this.hasClass("isChecked") ? removeItem : addItem)($this)
ClojureMostly
22

Le style ternaire est généralement utilisé pour économiser de l'espace. Sémantiquement, ils sont identiques. Je préfère utiliser la syntaxe complète if / then / else car je n'aime pas sacrifier la lisibilité - je suis old-school et je préfère mes accolades.

Le format complet if / then / else est utilisé pour à peu près tout. C'est particulièrement populaire si vous entrez dans de plus gros blocs de code dans chaque branche, vous avez un arbre if / else à branches multiples, ou plusieurs else / ifs dans une longue chaîne.

L'opérateur ternaire est courant lorsque vous attribuez une valeur à une variable basée sur une condition simple ou que vous prenez plusieurs décisions avec des résultats très brefs. L'exemple que vous citez n'a en fait aucun sens, car l'expression sera évaluée à l'une des deux valeurs sans aucune logique supplémentaire.

Bonnes idées:

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

Moins bon:

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

Une règle de base vraiment basique - pouvez-vous comprendre le tout aussi bien ou mieux sur une seule ligne? Ternary est OK. Sinon, développez-le.

Rêves surréalistes
la source
7

Il n'y a rien de particulièrement délicat dans l'exemple que vous avez publié.

Dans un opérateur ternaire, le premier argument (le conditionnel) est évalué et si le résultat est true, le deuxième argument est évalué et renvoyé, sinon le troisième est évalué et renvoyé. Chacun de ces arguments peut être n'importe quel bloc de code valide, y compris les appels de fonction.

Pense-y de cette façon:

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

Pourrait également être écrit comme:

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

Ceci est parfaitement valide et ces fonctions peuvent contenir n'importe quel code arbitraire, qu'il soit lié au renvoi d'une valeur ou non. De plus, les résultats de l'opération ternaire n'ont pas à être affectés à quoi que ce soit, tout comme les résultats de fonction ne doivent être affectés à rien:

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

Maintenant, remplacez-les simplement par des fonctions arbitraires, et vous vous retrouvez avec quelque chose comme votre exemple:

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

Maintenant, votre dernier exemple n'a vraiment pas besoin d'un ternaire, car il peut être écrit comme ceci:

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

Si vous allez imbriquer des opérateurs ternaires, je pense que vous voudrez faire quelque chose comme ceci:

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

C'est beaucoup plus efficace d'écrire / lire que:

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

Comme pour toute bonne programmation, les espaces rendent tout agréable pour les personnes qui doivent lire votre code une fois le projet terminé.

Sam W
la source
6
Pas du tout d'accord avec votre commentaire ci-dessus sur le fait que le ternaire imbriqué est plus facile à lire et à déboguer. Personnellement, je préférerais voir le bloc imbriqué else / if remplacé par une table de recherche ou une instruction switch.
JonnyReeves
@JonnyReeves est d'accord - généralement, la syntaxe ternaire imbriquée est mieux utilisée lors de la vérification de différentes conditions (par exemple, modulo de nombres )
AlexFoxGill
6

Je voudrais également ajouter quelque chose de moi.

Une autre syntaxe possible pour appeler des fonctions avec l'opérateur ternaire serait:

(condition ? fn1 : fn2)();

Cela peut être pratique si vous devez transmettre la même liste de paramètres aux deux fonctions, vous ne devez donc les écrire qu'une seule fois.

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

Vous pouvez utiliser l'opérateur ternaire même avec des noms de fonctions membres, ce que j'aime personnellement beaucoup pour économiser de l'espace:

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

ou

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

Un autre exemple:

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

Je sais que la question est déjà répondue.

Mais permettez-moi d'ajouter un point ici. Ce n'est pas seulement le cas du vrai ou du faux. Voir ci-dessous:

var val="Do";

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

Ici, si val est Do ou Done, c sera 7 sinon zéro. Dans ce cas, c sera 7.

C'est en fait une autre perspective de cet opérateur.

Himanshu Tiwari
la source