Opérateur ternaire Javascript vs ||

17

Je jetais un coup d'œil à du code node.js plus tôt, et j'ai remarqué que le gars qui l'a écrit semblait favoriser la syntaxe suivante:

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

Sur ce que je considère comme le plus concis:

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

Je me demandais si le deuxième formulaire est en fait une syntaxe JavaScript plus socialement acceptable, je l'ai vu dans la nature plus de fois que l'opérateur ternaire à cet effet.

Je note que dans le premier exemple, il utilise les doubles égaux (pas les triples égaux), ce qui signifie qu'il comptera «non défini» comme nul, ce qui réduirait un impact auquel je pourrais penser. Cependant, j'ai lu à de nombreux endroits que == est un opérateur plutôt mauvais en JavaScript (JSLint est très contre, IIRC).

Ed James
la source
2
Commentateurs: les commentaires sont destinés à demander des éclaircissements, pas à une discussion approfondie. Si vous avez une solution, laissez une réponse. Si votre solution est déjà publiée, veuillez la voter. Si vous souhaitez discuter de cette question avec d'autres personnes, veuillez utiliser le chat . Voir la FAQ pour plus d'informations.

Réponses:

17

Parce que ce code est évalué à "Valeur par défaut" à chaque fois que vous passez 0, "", false ou une autre valeur falsifiée.

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

Cela peut ne pas vous mordre sur la façon dont vous utilisez cette fonction particulière, mais c'est un mauvais schéma à éviter lorsque vous vous souciez de passer des choses comme des chaînes vides ou 0 ou un booléen.

Peter Smith
la source
vous devez uniquement utiliser une fusion nulle sur un objet, et si un objet est défini, cela ne fonctionnera pas. À l'exception peut-être de la chaîne vide.
Malfist
4
La comparaison zéro est un bon point, qui pourrait être assez inattendu.
Ed James
1
+1 - ce problème est précisément la raison pour laquelle Python a (éventuellement) ajouté la syntaxe "x if y else z". Ces sémantiques pour les opérateurs logiques sont assez courantes, et les mêmes erreurs courantes ont tendance à apparaître chaque fois que les idiomes comptent sur eux pour faire le travail des opérateurs de sélection conditionnelle.
Steve314
n'oubliez pas de mettre vos constructions entre parenthèses, si vous les utilisez avec la concaténation de chaînes var txt = 'Hello, ' + (user_name||'User') + '!';fonctionnera, mais sans parenthèses - vous obtiendrez undefined. jsfiddle.net/4mFAB/1
c69
7

Ce dont vous avez vraiment besoin, c'est d'un opérateur de fusion nul. Mais vu que javascript n'en a pas vraiment, les programmeurs utilisent généralement '||' pour le remplacer.

Cependant, les deux sont parfaitement raisonnables. Pour ceux qui ne comprennent pas ce qu'est un opérateur de fusion nul, l'opérateur ternaire est probablement plus susceptible d'être compris.

Malfist
la source
Un autre opérateur apparenté est l'opérateur Icon orthographié IIRC "else". Ceci reconnaît un résultat spécial "échec" du premier argument et utilise le deuxième argument dans ce cas comme alternative. Je souhaite en quelque sorte que les pythons "x if y else z" soient implémentés en utilisant deux opérateurs distincts - un opérateur d'assertion binaire "if" et un opérateur "else" de type icône - avec ces deux opérateurs pouvant être utilisés indépendamment. Cependant, Icon n'a pas pris en charge ce style, mais a fait quelque chose de bizarre avec des opérateurs relatifs.
Steve314
@ Steve314: Python a quelque chose que vous vouliez: un opérateur else séparé [false-part, true-part]avec un opérateur if séparé [..][bool(condition)]combiné [false-part, true-part][bool(condition)]. Si vous voulez un comportement paresseux, vous pouvez simplement lambda les parties vraie et fausse.
Lie Ryan