Operatori ternari in JavaScript senza "altro"


149

Ho sempre dovuto mettere nullnelle altre condizioni che non hanno nulla. C'è comunque intorno? Per esempio

condition ? x = true : null;

in sostanza, c'è un modo per fare:

condition ? x = true;

Ora si presenta come un errore di sintassi

Cordiali saluti, ecco un vero esempio di codice:

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

21
l'uso di un ternario come condition ? x = true : null;dovrebbe probabilmente essere scritto come x = (condition ? true : null);. A parte questo, in javascript si nullvaluta falso, quindi in questo caso è possibile x = (condition);e ottenere lo stesso risultato.
Matt S,

1
opaca, la tua risposta è la migliore, ma non è una risposta, è un commento!
Cheeso,

Matt, il mio codice ACTUAL è:! Defaults.slideshowWidth? defaults.slideshowWidth = obj.find ('img'). width () + 'px': null; un modo più breve e migliore per scriverlo?
Oscar Godson,

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

sarebbe meglio evitare l'assegnazione dell'identità, quindi questa dovrebbe essere solo una condizione:if (!defaults.slideshowWidth) defaults.slideshowWidth = obj.find('img').width()+'px'
Mihail Malostanidis

Risposte:


226

Prima di tutto, un'espressione ternaria non sostituisce un costrutto if / else, è equivalente a un costrutto if / else che restituisce un valore. Cioè, una clausola if / else è codice, un'espressione ternaria è un'espressione , nel senso che restituisce un valore.

Ciò significa diverse cose:

  • usa espressioni ternarie solo quando hai una variabile sul lato sinistro a =cui deve essere assegnato il valore di ritorno
  • utilizzare le espressioni ternarie solo quando il valore restituito deve essere uno dei due valori (oppure utilizzare espressioni nidificate se è appropriato)
  • ogni parte dell'espressione (dopo? e dopo:) dovrebbe restituire un valore senza effetti collaterali (l'espressione x = truerestituisce vero in quanto tutte le espressioni restituiscono l'ultimo valore, ma cambia anche x senza che x abbia alcun effetto sul valore restituito)

In breve: l'uso "corretto" di un'espressione ternaria è

var resultofexpression = conditionasboolean ? truepart: falsepart;

Invece del tuo esempio condition ? x=true : null ;, in cui usi un'espressione ternaria per impostare il valore di x, puoi usare questo:

 condition && (x = true);

Questa è ancora un'espressione e potrebbe quindi non superare la convalida, quindi sarebbe un approccio ancora migliore

 void(condition && x = true);

L'ultimo passerà la convalida.

Ma poi di nuovo, se il valore atteso è un valore booleano, basta usare il risultato dell'espressione condizione stessa

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

AGGIORNAMENTO In relazione al tuo campione questo è probabilmente più appropriato:

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

4
brillante SO, che non consente alla modifica di correggere l' i/elseerrore di battitura in quanto non è sufficiente caratteri.
Rugiada

1
void (condition && x = true) - sembra fantastico ma sembra gettare l'errore "assegnazione non valida lato sinistro"
Eugene Tiurin,

1
void (condition && (x = true)) // mantiene il compito separato dal primo valore
diamondsea

4
Tuttavia, questo non è intuitivo da leggere, soprattutto per gli sviluppatori non abituati a questo stile. Potresti scrivere altrettanto facilmente e più facilmente come: if (condition) {x = true; }
diamondsea

2
Potresti spiegare cosa intendi con "potrebbe non superare la convalida"? Non capisco perché si debba racchiudere l'espressione void(). Grazie.
Gilad Mayani,

20

No, ha bisogno di tre operandi. Ecco perché sono chiamati operatori ternari .

Tuttavia, per quello che hai come esempio, puoi farlo:

if(condition) x = true;

Sebbene sia più sicuro avere delle parentesi graffe se in futuro è necessario aggiungere più di un'istruzione:

if(condition) { x = true; }

Modifica: ora che hai menzionato il codice effettivo a cui si applica la tua domanda:

if(!defaults.slideshowWidth)
    { defaults.slideshowWidth = obj.find('img').width()+'px'; }

1
Puoi, ma non dovresti. Almeno non senza parentesi graffe attorno ad esso - è molto soggetto a errori.
Konerak,

1
è vero? Ho capito che il motivo principale per cui sono necessari i ricci è perché rendono più semplice la vita di jslint.
Cheeso,

@Cheeso è soggetto a errori nel senso del refactoring. Tornate per aggiungere altro da fare nel caso di una vera condizione senza rendervi conto che non ci sono parentesi graffe lì. Il nuovo codice verrà sempre eseguito anziché nel caso di quando vero.
Matt S,

No, lo so, mi piace solo scrivere condizionali senza extra come if () {} else {} quando è uguale a semplicemente?:;
Oscar Godson,

3
Onestamente, non ho mai conosciuto gli sviluppatori più spaventati dall'uso di un linguaggio di Javascript: -PI non vorrebbe che qualcuno mi dicesse che non avrei dovuto usare le parentesi graffe. Li ometto molto e non ho mai più problemi di quanti mi perderei accidentalmente un tutore.
Andy E,

12

Più spesso le persone si avvalgono di operatori logici per abbreviare la sintassi dell'istruzione:

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

Ma nel tuo caso particolare la sintassi può essere ancora più semplice

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

Questo codice restituirà il defaults.slideshowWidthvalore se defaults.slideshowWidthviene valutato su true e obj.find('img').width()+'px'valore in caso contrario.

Per i dettagli, consultare la valutazione del corto circuito degli operatori logici.


11
var x = condition || null;

2
(defaults.slideshowWidth) || (defaults.slideshowWidth = obj.find('img').width()+'px')oppuredefaults.slideshowWidth = defaults.slideshowWidth || (obj.find('img').width()+'px')
Casey Chu,

> Restituisce expr1 se può essere convertito in vero; in caso contrario, restituisce expr2. Operatori logici (MDN)
Szabolcs Páll

5

Potresti scrivere

x = condition ? true : x;

In modo che x non sia modificato quando la condizione è falsa.

Questo quindi equivale a

if (condition) x = true

MODIFICARE:

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

Ci sono un paio di alternative - non sto dicendo che sono migliori / peggiori - solo alternative

Il passaggio a null come terzo parametro funziona perché il valore esistente è null. Se si esegue il refactoring e si modifica la condizione, sussiste il pericolo che ciò non sia più vero. Passando il valore esistente come la seconda scelta nelle guardie ternarie contro questo:

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

Più sicuro, ma forse non così bello da guardare, e più digitando. In pratica, probabilmente scriverei

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

Un po 'di codice live è (comunque sbarazzarsi del null in questo?):! Defaults.slideshowWidth? defaults.slideshowWidth = obj.find ('img'). width () + 'px': null;
Oscar Godson,

2

Nel tuo caso vedo l'operatore ternario come ridondante. È possibile assegnare la variabile direttamente all'espressione, utilizzando gli operatori ||, &&.

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

diventerà :

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

È più chiaro, è più stile "javascript".


2

Che dire semplicemente

    if (condition) { code if condition = true };

1

Per utilizzare un operatore ternario senza altro all'interno di un array o di una dichiarazione oggetto, è possibile utilizzare l'operatore di diffusione ES6 ...()

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

E per gli oggetti:

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

fonte originale

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.