Exemplo de operador ternário JavaScript com funções

91

Estou usando o jQuery 1.7.1

Estou apenas começando a usar o operador ternário JavaScript para substituir instruções if / else simples. Fiz isso com sucesso em vários lugares. Fiquei surpreso quando consegui fazer outra coisa funcionar, quando pensei que com certeza não funcionaria, mas tentei mesmo assim.

Aqui está a declaração original:

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

Aqui está a mesma função usando o operador ternário:

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

Fiquei surpreso porque todos os exemplos que vi sendo usados ​​estavam meramente definindo variáveis ​​como esta:

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

Minha pergunta é se esse é um uso "normal" e funcionará na maioria das versões do JavaScript? Onde isso vai falhar? Existem outros usos menos óbvios para isso?

ATUALIZAÇÃO - Obrigado pelo conselho do "mundo real" !!!

Estou usando isso como minha função:

function updateItem() {
    $this = $(this);
    $this.hasClass("IsChecked") ? removeItem($this) : addItem($this);
}
Evik James
fonte
É normal e funcionará bem. Em geral, a legibilidade é difícil ao usar operadores ternários, mas no seu caso parece ótimo.
Selvakumar Arumugam
1
Hmm .... você também pode fazer isso, pois ambos aceitam os mesmos argumentos (IsChecked ? removeItem : addItem)($this). No entanto, para responder à sua pergunta, sim, isso é normal e não há nada de errado em usar operadores ternários, desde que eles não prejudiquem a capacidade de manutenção ou legibilidade em uma situação onde isso é necessário. jsfiddle.net/vsB3f
Kevin B,
if($this.hasClass("IsChecked")) removeItem($this); else addItem($this)é a maneira correta. O operador ternário não se destina a casos como este, mas a coisas como foo(isChecked ? 'bar' : meow());(ou seja, quando você se preocupa com o "valor de retorno" de tudo o que você faz nos blocos then / else)
ThiefMaster
1
Em seu exemplo, pule a primeira linha em favor disso: $(this).hasClass("IsChecked") ? removeItem($this) : addItem($this); Eu posso entender seu código como está em uma linha, então ele se encaixa na minha regra (veja a postagem abaixo). Funciona para mim.
Surreal Dreams

Respostas:

189

Heh, existem alguns usos muito interessantes da sintaxe ternária em sua pergunta; Eu gosto mais do último ...

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

O uso de ternário aqui é totalmente desnecessário - você pode simplesmente escrever

x = (1 < 2);

Da mesma forma, o elemento de condição de uma instrução ternária é sempre avaliado como um valor booleano, portanto, você pode expressar:

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

Simplesmente como:

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

Na verdade, eu também removeria o IsCheckedtemporário, o que deixa você com:

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

Quanto a se essa sintaxe é aceitável, com certeza é! É uma ótima maneira de reduzir quatro linhas de código em uma, sem afetar a legibilidade. O único conselho que eu lhe daria é evitar aninhar várias declarações ternárias na mesma linha (isso é loucura!)

JonnyReeves
fonte
note que você pode querer evitar o uso de letras maiúsculas em nomes de classe (IsChecked tornando-se is-checks) stackoverflow.com/questions/1547986/…
Adrien Be
JS tem funções de primeira classe:($this.hasClass("isChecked") ? removeItem : addItem)($this)
ClojureMostly
22

O estilo ternário é geralmente usado para economizar espaço. Semanticamente, eles são idênticos. Eu prefiro ir com a sintaxe if / then / else completa porque não gosto de sacrificar a legibilidade - sou da velha guarda e prefiro meu aparelho.

O formato if / then / else completo é usado para praticamente tudo. É especialmente popular se você entrar em blocos maiores de código em cada branch, você tiver uma árvore if / else muti-ramificada ou vários else / ifs em uma longa string.

O operador ternário é comum quando você atribui um valor a uma variável com base em uma condição simples ou quando toma várias decisões com resultados muito breves. O exemplo que você cita realmente não faz sentido, porque a expressão será avaliada como um dos dois valores sem nenhuma lógica extra.

Boas idéias:

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

Menos bom:

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

Uma regra realmente básica - você pode entender tudo tão bem ou melhor em uma linha? Ternário está bem. Caso contrário, expanda-o.

Sonhos surreais
fonte
7

Não há nada particularmente complicado no exemplo que você postou.

Em um operador ternário, o primeiro argumento (o condicional) é avaliado e se o resultado for true, o segundo argumento é avaliado e retornado, caso contrário, o terceiro é avaliado e retornado. Cada um desses argumentos pode ser qualquer bloco de código válido, incluindo chamadas de função.

Pense desta forma:

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

Também pode ser escrito como:

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

Isso é perfeitamente válido e essas funções podem conter qualquer código arbitrário, esteja ele relacionado ao retorno de um valor ou não. Além disso, os resultados da operação ternária não precisam ser atribuídos a nada, assim como os resultados da função não precisam ser atribuídos a nada:

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

Agora, basta substituí-los por quaisquer funções arbitrárias e você terá algo como o seu exemplo:

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

Agora, seu último exemplo realmente não precisa de um ternário, pois pode ser escrito assim:

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

Se você vai aninhar operadores ternários, acredito que você queira fazer algo assim:

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

É muito mais eficiente de escrever / ler do que:

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

Como acontece com toda boa programação, o espaço em branco torna tudo bom para as pessoas que precisam ler seu código depois de concluir o projeto.

Sam W
fonte
6
Discordo totalmente do seu comentário acima sobre o ternário aninhado ser mais fácil de ler e depurar. Pessoalmente, prefiro ver o bloco aninhado else / if substituído por uma tabela de pesquisa ou por uma instrução switch.
JonnyReeves
@JonnyReeves concordou - geralmente a sintaxe ternária aninhada é melhor usada ao verificar diferentes condições (por exemplo, módulo de números )
AlexFoxGill
6

Eu também gostaria de acrescentar algo de mim.

Outra sintaxe possível para chamar funções com o operador ternário seria:

(condition ? fn1 : fn2)();

Pode ser útil se você tiver que passar a mesma lista de parâmetros para ambas as funções, então você terá que escrevê-los apenas uma vez.

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

Você pode usar o operador ternário até mesmo com nomes de funções-membro, que eu pessoalmente gosto muito para economizar espaço:

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

ou

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

Outro exemplo:

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

Eu sei que a pergunta já foi respondida.

Mas deixe-me acrescentar um ponto aqui. Este não é apenas o caso de verdadeiro ou falso. Ver abaixo:

var val="Do";

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

Aqui, se val for Do ou Done, então c será 7, caso contrário, será zero. Nesse caso, c será 7.

Esta é na verdade outra perspectiva deste operador.

Himanshu Tiwari
fonte