Un'istruzione if javascript con più condizioni le verifica tutte?


100

In javascript, quando si utilizza un'istruzione if con più condizioni da verificare, javascript le verifica tutte a prescindere o si salva prima di testarle tutte se è già false?

Per esempio:

 a = 1
 b = 2
 c = 1

 if (a==1 && b==1 && c==1)

JavaScript verificherà tutte e 3 queste condizioni o, dopo aver visto che b non è uguale a 1, ed è quindi falso, uscirà dall'istruzione?

Chiedo dal punto di vista delle prestazioni. Se, ad esempio, sto testando 3 selettori jQuery complessi, preferirei che jQuery attraversi il DOM 3 volte se è ovvio tramite il primo che restituirà FALSE. (In tal caso avrebbe più senso annidare 3 istruzioni if).

APPENDICE: Più di una curiosità, qual è il termine corretto per questo? Ho notato che molti di voi usano il termine "cortocircuito". Inoltre, alcune lingue fanno questo e altre no?


@ Josh: apprezzo completamente l'idea che si tratti di microottimizzazione. Buono a sapersi. Detto questo, se un'opzione è più ottimizzata di un'altra, presumo sia bene conoscerla e prendere l'abitudine di utilizzare tale metodo. (Inoltre, beh, ero solo molto curioso anche della risposta)
DA.

21
A rigor di termini, questa non è un'ottimizzazione prematura. Nei linguaggi con logica di cortocircuito, è importante sapere in quali condizioni alcuni metodi non verranno eseguiti; se ti affidi ai loro effetti collaterali, ad esempio.
Rob il

5
Ecco un'altra domanda sulla "valutazione del cortocircuito": stackoverflow.com/questions/1232603/…
David

@David. Grazie! Lettura interessante.
DA.

Risposte:


151

L' &&operatore "cortocircuiti", cioè se la condizione di sinistra è falsa, non si preoccupa di valutare quella di destra.

Allo stesso modo, l' ||operatore va in cortocircuito se la condizione di sinistra è vera.

EDIT: Tuttavia, non dovresti preoccuparti delle prestazioni finché non hai valutato e determinato che è un problema. La microottimizzazione prematura è la rovina della manutenibilità.


1
Ottima risposta (sia la parte tecnica che la questione gestionale). Grazie!
DA.

5
Se vuoi che esegua tutte le parti della dichiarazione booleana, puoi usare & e | per e eo ripetutamente
Zoidberg

25
Questa condizione non riguarda necessariamente le prestazioni. A volte potresti fare un controllo nullo e dire se il tuo controllo nullo è la condizione a e poi provi a fare a (b == valore + 1) per il tuo secondo controllo otterrai un errore se tutte e tre le condizioni se le condizioni sono state verificate.
infocyde

4
In effetti, il cortocircuito non riguarda le prestazioni. La domanda originale, tuttavia, era da un punto di vista delle prestazioni.
Anon.

1
molto bene. Fare questo tipo di micro ottimizzazione (tra le altre) può avere un grande impatto all'interno di un ciclo di eventi di scorrimento, ad esempio per il calcolo della parallasse di più elementi, ad esempio o anche per una barra adesiva. prendi questo ex: if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)la seconda condizione è un calcolo più costoso, la prima è solo un booleano. :)
antoni

13

Dal punto di vista delle prestazioni, questa non è una microottimizzazione.

Se abbiamo 3 variabili booleane, a, b, c è una microottimizzazione.

Se chiamiamo 3 funzioni che restituiscono variabili booleane, ciascuna funzione può richiedere molto tempo, e non solo è importante conoscere questo cortocircuito, ma in quale ordine. Per esempio:

if (takesSeconds() && takesMinutes())

è molto meglio di

if (takesMinutes() && takesSeconds())

se entrambi hanno la stessa probabilità di restituire false.


12

Ecco perché puoi fare in codice javascript come

var x = x || 2;

Il che significherebbe che se x è indefinito o altrimenti "falso", il valore predefinito è 2.


3
Questo potrebbe funzionare anche se JS non supportasse la valutazione del cortocircuito.
pswg

1
È l'equivalente di un ternario?
Mark Carpenter Jr

10

Nel caso qualcuno si chieda se esiste un modo per forzare la valutazione di tutte le condizioni, in alcuni casi possono essere utilizzati gli operatori bit a bit &e|

var testOr = true | alert(""); //alert pops up
var testAnd = false & alert(""); //alert pops up

Questi dovrebbero essere usati con molta attenzione perché gli operatori bit per bit sono operatori aritmetici che lavorano su singoli bit del loro operando e non possono sempre funzionare come versione "non cortocircuitata" di &&e||

Esempio:

-2147483648 && 1 = 1 

ma

-2147483648 & 1 = 0

Spero che aiuti qualcuno che è arrivato qui alla ricerca di informazioni come questa (come me) e grazie a @Max per la correzione e il controesempio


1
Questa risposta è sbagliata. & e | sono operatori bit per bit, NON sono "versioni non in cortocircuito di && e ||". Gli operatori bit per bit sono operatori aritmetici che lavorano su singoli bit del loro operando. Esempio: -2147483648 && 1 = 1 ma -2147483648 & 1 = 0. Maggiori informazioni qui: en.wikipedia.org/wiki/Bitwise_operation
Max

1
@ Max in realtà non lo sapevo, l'ho usato (quello che ora chiamo "trucco") da quando stavo studiando C. Fortunatamente tali input che avrebbero rotto il mio codice non sono mai venuti fuori. Ho corretto la mia risposta, te lo devo
ivcandela

@DJDaveMark scusa non sono riuscito a far funzionare la tua false && (alert(""))soluzione: /
ivcandela

@ivcandela Nemmeno io. Se non fossi stato sul mio telefono lo avrei provato prima; o) Peccato che tu non possa modificare i commenti. L'ho appena cancellato e ne ho aggiunto un altro sotto
DJDaveMark

Il modo più semplice e migliore per forzare la valutazione è salvare i risultati in variabili, quindi testarli rispetto alle variabili, ad esempio:var a=false; var b=check(); alert(a && b);
DJDaveMark

7

Testerà tutte le condizioni solo se le prime sono vere, provalo tu stesso:

javascript: alert (false && alert("A") && false);

3

È in cortocircuito: nel tuo esempio verranno confrontati solo aeb.


3

Un altro motivo per interrompere la valutazione con 1 o più parametri a sinistra.

if (response.authResponse && (response.authResponse.accessToken! = user.accessToken)) {...}

la seconda valutazione si basa sul fatto che la prima sia vera e non genererà un errore di compilazione se response.authResponse è nullo o non definito ecc. perché la prima condizione non è riuscita.

Altre lingue avevano questo problema nei primi giorni e penso che sia un approccio standard nella creazione di compilatori ora.


2

Esce dopo aver visto che b non è uguale a uno.


2

Per chiunque su questa domanda sia confuso perché non vede il comportamento di cortocircuito quando utilizza un ||insieme a un ?operatore in questo modo:

x = 1 || true ? 2 : 3 // value of x will be 2, rather than 1 as expected

sembra che la regola del cortocircuito non funzioni. Perché valuta il secondo termine del ||(vero? 2: 3) quando il primo è vero? Risulta essere un problema dell'ordine delle operazioni perché quanto sopra è l'equivalente di

x = (1 || true) ? 2 : 3

con la ||prima valutata e la ?seconda valutata. Quello che probabilmente vuoi è:

x = 1 || (true ? 2 : 3)

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.