Operadores ternários em JavaScript sem um "outro"

149

Eu sempre tive que colocar nullnas outras condições que não têm nada. Existe alguma maneira de contornar isso? Por exemplo

condition ? x = true : null;

Basicamente, existe uma maneira de fazer:

condition ? x = true;

Agora ele aparece como um erro de sintaxe

Para sua informação, aqui estão alguns exemplos de códigos reais:

!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null;
Oscar Godson
fonte
21
o uso de um ternário como condition ? x = true : null;provavelmente deve ser escrito como x = (condition ? true : null);. Como um aparte, em javascript é nullavaliado como falso, portanto, neste caso, você poderia x = (condition);e obter o mesmo resultado.
Matt S
1
mate, sua resposta é melhor, mas não é uma resposta, é um comentário!
Cheeso 28/05
Matt, meu código REAL é:! Defaults.slideshowWidth? defaults.slideshowWidth = obj.find ('img'). width () + 'px': nulo; uma maneira melhor e mais curta de escrever isso?
Oscar Godson
2
defaults.slideshowWidth = defaults.slideshowWidth || obj.find ('img'). width () + 'px';
Kennebec 29/05
seria melhor para evitar a atribuição de identidade, de modo que este deve ser apenas uma condição:if (!defaults.slideshowWidth) defaults.slideshowWidth = obj.find('img').width()+'px'
Mihail Malostanidis

Respostas:

226

Antes de tudo, uma expressão ternária não substitui uma construção if / else - é equivalente a uma construção if / else que retorna um valor. Ou seja, uma cláusula if / else é código, uma expressão ternária é uma expressão , o que significa que ela retorna um valor.

Isso significa várias coisas:

  • use expressões ternárias somente quando você tiver uma variável no lado esquerdo da =qual será atribuído o valor de retorno
  • use apenas expressões ternárias quando o valor retornado for um dos dois valores (ou use expressões aninhadas, se for o caso)
  • cada parte da expressão (após? e após:) deve retornar um valor sem efeitos colaterais (a expressão x = trueretorna true, pois todas as expressões retornam o último valor, mas também altera x sem que x tenha efeito sobre o valor retornado)

Em resumo - o uso "correto" de uma expressão ternária é

var resultofexpression = conditionasboolean ? truepart: falsepart;

Em vez do seu exemplo condition ? x=true : null ;, onde você usa uma expressão ternária para definir o valor de x, pode usar o seguinte:

 condition && (x = true);

Essa ainda é uma expressão e, portanto, pode não ser aprovada na validação; portanto, uma abordagem ainda melhor seria

 void(condition && x = true);

O último passará na validação.

Mas, novamente, se o valor esperado for um booleano, basta usar o resultado da própria expressão de condição

var x = (condition); // var x = (foo == "bar");

ATUALIZAÇÃO Em relação à sua amostra, isso provavelmente é mais apropriado:

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';
Sean Kinsey
fonte
4
SO brilhante, não permitindo que a edição corrija i/elseerros de digitação, pois não há caracteres suficientes.
dewd
1
void (condition && x = true) - isso parece ótimo, mas parece
gerar o
1
void (condição && (x = true)) // mantém a atribuição separada do primeiro valor
diamondsea
4
No entanto, isso não é intuitivo de ler, especialmente para desenvolvedores não acostumados a esse estilo. Você poderia escrever isso de maneira tão fácil e mais fácil como: if (condition) {x = true; }
diamondsea
2
Você poderia explicar o que você quer dizer com "pode ​​não passar na validação"? Não entendo por que se deve envolver a expressão void(). obrigado.
gilad Mayani
20

Não, ele precisa de três operandos. É por isso que eles são chamados de operadores ternários .

No entanto, para o que você tem como exemplo, você pode fazer o seguinte:

if(condition) x = true;

Embora seja mais seguro usar chaves, se você precisar adicionar mais de uma instrução no futuro:

if(condition) { x = true; }

Editar: agora que você mencionou o código real no qual sua pergunta se aplica a:

if(!defaults.slideshowWidth)
    { defaults.slideshowWidth = obj.find('img').width()+'px'; }
Em sílico
fonte
1
Você pode, mas não deveria. Pelo menos não sem colchetes - é muito propenso a erros.
Konerak 28/05
1
isso é verdade? Entendi que o principal motivo para exigir curlies é porque eles facilitam a vida de jslint.
Cheeso 28/05
@ Chees é propenso a erros no sentido de refatorar. Você volta para adicionar mais o que fazer no caso de uma condição verdadeira, sem perceber que não há chaves aqui. O novo código sempre será executado, e não o caso, quando verdadeiro.
Matt S
Não, eu sei, eu apenas gosto de escrever condicionais sem extras, como if () {} else {} quando é igual a simplesmente?:;
Oscar Godson
3
Honestamente, nunca conheci desenvolvedores com mais medo de usar uma linguagem que o Javascript: -PI não gostaria que alguém me dissesse que eu não deveria usar chaves. Eu os omito muito e nunca tenho mais problemas do que acidentalmente perdi uma chave.
Andy E
12

Com mais frequência, as pessoas usam operadores lógicos para reduzir a sintaxe da instrução:

!defaults.slideshowWidth &&
  (defaults.slideshowWidth = obj.find('img').width()+'px');

Mas, no seu caso particular, a sintaxe pode ser ainda mais simples

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';

Este código retornará o defaults.slideshowWidthvalor se defaults.slideshowWidthfor avaliado como true e, obj.find('img').width()+'px'caso contrário, será valor.

Consulte a Avaliação de curto-circuito de operadores lógicos para obter detalhes.

Eugene Tiurin
fonte
11
var x = condition || null;
philfreo
fonte
2
(defaults.slideshowWidth) || (defaults.slideshowWidth = obj.find('img').width()+'px')oudefaults.slideshowWidth = defaults.slideshowWidth || (obj.find('img').width()+'px')
Casey Chu
> Retorna expr1 se puder ser convertido para true; caso contrário, retorna expr2. Operadores lógicos (MDN)
Szabolcs Páll
5

Você poderia escrever

x = condition ? true : x;

Portanto, x não é modificado quando a condição é falsa.

Isso então é equivalente a

if (condition) x = true

EDITAR:

!defaults.slideshowWidth 
      ? defaults.slideshowWidth = obj.find('img').width()+'px' 
      : null 

Existem algumas alternativas - não estou dizendo que são melhores / piores - apenas alternativas

Passar nulo como o terceiro parâmetro funciona porque o valor existente é nulo. Se você refatorar e alterar a condição, existe o risco de que isso não seja mais verdade. Passando o valor existente como a segunda opção nas proteções ternárias contra isso:

!defaults.slideshowWidth = 
      ? defaults.slideshowWidth = obj.find('img').width()+'px' 
      : defaults.slideshowwidth 

Mais seguro, mas talvez não tão agradável de se olhar, e mais digitado. Na prática, eu provavelmente escreveria

defaults.slideshowWidth = defaults.slideshowWidth 
               || obj.find('img').width()+'px'
mdma
fonte
Algum código ativo é (de qualquer forma, para se livrar do nulo?):! Defaults.slideshowWidth? defaults.slideshowWidth = obj.find ('img'). width () + 'px': nulo;
Oscar Godson
2

No seu caso, vejo o operador ternário como redundante. Você pode atribuir a variável diretamente à expressão, usando os operadores ||, &&.

!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null ;

se tornará :

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';

É mais claro, é mais estilo "javascript".

Krasimir Kirilov
fonte
2

Que tal simplesmente

    if (condition) { code if condition = true };
Yandiro
fonte
1

Para usar um Operador Ternário sem mais dentro de uma declaração de matriz ou objeto, você pode usar o operador de dispersão ES6 ...()

const cond = false;
const arr = [
  ...(cond ? ['a'] : []),
  'b',
];
    // ['b']

E para objetos:

const cond = false;
const obj = {
  ...(cond ? {a: 1} : {}),
  b: 2,
};
    // {b: 2}

fonte original

fogx
fonte