Operadores ternarios en JavaScript sin un "otro"

149

Siempre he tenido que poner nulllas condiciones que no tienen nada. ¿Hay alguna manera de evitarlo? P.ej

condition ? x = true : null;

Básicamente, ¿hay alguna manera de hacerlo?

condition ? x = true;

Ahora aparece como un error de sintaxis

Para su información, aquí hay un código de ejemplo real:

!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null;
Oscar Godson
fuente
21
El uso de un ternario como condition ? x = true : null;probablemente debería escribirse como x = (condition ? true : null);. Por otro lado, en javascript se nullevalúa como falso, por lo que en ESTE caso podría x = (condition);lograr el mismo resultado.
Matt S
1
Matt, tu respuesta es la mejor, pero no es una respuesta, ¡es un comentario!
Cheeso
Matt, mi código REAL es:! Defaults.slideshowWidth? defaults.slideshowWidth = obj.find ('img'). width () + 'px': nulo; ¿Una forma mejor y más corta de escribir eso?
Oscar Godson
2
defaults.slideshowWidth = defaults.slideshowWidth || obj.find ('img'). ancho () + 'px';
kennebec
sería mejor evitar la asignación de identidad, por lo que esto debería ser una condición:if (!defaults.slideshowWidth) defaults.slideshowWidth = obj.find('img').width()+'px'
Mihail Malostanidis

Respuestas:

226

En primer lugar, una expresión ternaria no es un reemplazo para una construcción if / else, es un equivalente a una construcción if / else que devuelve un valor. Es decir, una cláusula if / else es código, una expresión ternaria es una expresión , lo que significa que devuelve un valor.

Esto significa varias cosas:

  • use expresiones ternarias solo cuando tenga una variable en el lado izquierdo del = que se le asignará el valor de retorno
  • solo use expresiones ternarias cuando el valor devuelto sea uno de dos valores (o use expresiones anidadas si eso es apropiado)
  • cada parte de la expresión (después de? y después:) debe devolver un valor sin efectos secundarios (la expresión x = truedevuelve verdadero ya que todas las expresiones devuelven el último valor, pero también cambia x sin que x tenga ningún efecto en el valor devuelto)

En resumen: el uso 'correcto' de una expresión ternaria es

var resultofexpression = conditionasboolean ? truepart: falsepart;

En lugar de su ejemplo condition ? x=true : null ;, donde usa una expresión ternaria para establecer el valor de x, puede usar esto:

 condition && (x = true);

Esto sigue siendo una expresión y, por lo tanto, podría no pasar la validación, por lo que un enfoque aún mejor sería

 void(condition && x = true);

El último pasará la validación.

Pero, de nuevo, si el valor esperado es un valor booleano, simplemente use el resultado de la expresión de condición en sí

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

ACTUALIZACIÓN En relación con su muestra, esto probablemente sea más apropiado:

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';
Sean Kinsey
fuente
44
SO brillante, que no permite editar para corregir i/elseerrores tipográficos, ya que no hay suficientes caracteres.
rocío
1
nulo (condición && x = verdadero) - esto se ve muy bien pero parece arrojar el error "asignación no válida del lado izquierdo"
Eugene Tiurin
1
nulo (condición && (x = verdadero)) // mantiene la asignación separada del primer valor
diamondsea
44
Sin embargo, esto no es intuitivo de leer, especialmente para los desarrolladores que no están acostumbrados a este estilo. Podrías escribir esto con la misma facilidad y facilidad como: if (condición) {x = verdadero; }
diamondsea
2
¿Podría explicar qué quiere decir con "podría no pasar la validación"? No entiendo por qué uno debería envolver la expresión void(). Gracias.
gilad mayani
20

No, necesita tres operandos. Por eso se llaman ternarios operadores .

Sin embargo, para lo que tiene como ejemplo, puede hacer esto:

if(condition) x = true;

Aunque es más seguro tener llaves si necesita agregar más de una declaración en el futuro:

if(condition) { x = true; }

Editar: ahora que menciona el código real en el que se aplica su pregunta:

if(!defaults.slideshowWidth)
    { defaults.slideshowWidth = obj.find('img').width()+'px'; }
En silico
fuente
1
Puedes, pero no deberías. Al menos no sin llaves alrededor, es muy propenso a errores.
Konerak
1
¿es eso cierto? Comprendí que la razón principal para requerir curlies es porque hacen que la vida de jslint sea más fácil.
Cheeso
@Cheeso es propenso a errores en el sentido de refactorización. Vuelve para agregar más cosas que hacer en el caso de una condición verdadera sin darse cuenta de que no hay llaves allí. El nuevo código siempre se ejecutará en lugar del caso de cuando es verdadero.
Matt S
No, lo sé, simplemente me gusta escribir condicionales sin extras como if () {} else {} cuando es igual a simplemente?:;
Oscar Godson
3
Honestamente, nunca he conocido a los desarrolladores que tengan más miedo de usar un lenguaje que Javascript: -PI no quisiera que alguien me dijera que no debo usar llaves. Los omito mucho y nunca tengo más problemas de los que accidentalmente me faltaría un aparato ortopédico.
Andy E
12

Con mayor frecuencia, las personas utilizan operadores lógicos para acortar la sintaxis de la declaración:

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

Pero en su caso particular, la sintaxis puede ser aún más simple

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

Este código devolverá el defaults.slideshowWidthvalor si defaults.slideshowWidthse evalúa como verdadero yobj.find('img').width()+'px' valor de lo contrario.

Consulte la Evaluación de cortocircuito de operadores lógicos para obtener más detalles.

Eugene Tiurin
fuente
11
var x = condition || null;
philfreo
fuente
2
(defaults.slideshowWidth) || (defaults.slideshowWidth = obj.find('img').width()+'px')odefaults.slideshowWidth = defaults.slideshowWidth || (obj.find('img').width()+'px')
Casey Chu
> Devuelve expr1 si se puede convertir a verdadero; de lo contrario, devuelve expr2. Operadores lógicos (MDN)
Szabolcs Páll
5

Podrías escribir

x = condition ? true : x;

De modo que x no se modifica cuando la condición es falsa.

Esto es equivalente a

if (condition) x = true

EDITAR:

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

Hay un par de alternativas, no digo que sean mejores o peores, simplemente alternativas

Pasar nulo como el tercer parámetro funciona porque el valor existente es nulo. Si refactoriza y cambia la condición, existe el peligro de que esto ya no sea cierto. Transmitir el valor existente como la segunda opción en los guardias ternarios contra esto:

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

Más seguro, pero quizás no tan agradable a la vista, y más mecanografía. En la práctica, probablemente escribiría

defaults.slideshowWidth = defaults.slideshowWidth 
               || obj.find('img').width()+'px'
mdma
fuente
Algún código en vivo es (de todos modos para deshacerse del nulo en esto?):! Defaults.slideshowWidth? defaults.slideshowWidth = obj.find ('img'). width () + 'px': nulo;
Oscar Godson
2

En su caso, veo al operador ternario como redundante. Puede asignar la variable directamente a la expresión, utilizando los operadores ||, &&.

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

se convertirá :

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

Está más claro, es más estilo "javascript".

Krasimir Kirilov
fuente
2

¿Qué tal simplemente?

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

Para usar un operador ternario sin otra cosa dentro de una declaración de matriz u objeto, puede usar el operador de propagación ES6 ...()

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

Y para objetos:

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

fuente original

fogx
fuente