Interruttore Javascript vs. if ... else if ... else


143

Ragazzi, ho un paio di domande:

  1. Esiste una differenza di prestazioni in JavaScript tra switchun'istruzione e un if...else?
  2. Se sì, perché?
  3. È il comportamento di switche if...elsediverso in tutti i browser? (FireFox, IE, Chrome, Opera, Safari)

Il motivo per cui ho posto questa domanda è che sembra che ottenga prestazioni migliori su una switchdichiarazione con circa 1000 casi in Firefox.


Modificato sfortunatamente questo non è il mio codice, Javascript viene prodotto sul lato server da una libreria compilata e non ho accesso al codice. Viene chiamato il metodo che sta producendo javascript

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

la nota arrayofvaluesè un elenco separato da virgole.

ciò che produce è

function [name] (value) {
  if (value == [value from array index x]) {
     [action from array index x]
  }
}

Nota: dove [name]= il nome è passato alla funzione lato server

Ora ho modificato l'output della funzione da inserire in un oggetto TextArea, ho scritto del codice JavaScript per analizzare la funzione e l'ho convertito in una serie di caseistruzioni.

finalmente eseguo la funzione e funziona bene ma le prestazioni differiscono in IE e Firefox.


1
Vorrei suggerire un esempio di codice per esaminare ciò che è ottimale. Voglio dire, ci deve essere un motivo per cui lo stai chiedendo, giusto?
jcolebrand,

Per favore pubblica quello che stai facendo, perché ci sono pochissimi casi nella mia lunga esperienza per i quali direi una dichiarazione switch da 100 case o una serie da 100 parti se / else fosse una buona idea.
Pointy,

scusate ragazzi non 100 ma migliaia di condizioni
John Hartsock,

2
Tutti, grazie per l'input. Ma il mio problema non era in realtà la differenza tra le dichiarazioni if ​​e swith. Era il codice in esecuzione all'interno dell'istruzione. +1 a tutti voi per il vostro aiuto. Scusate l'inconveniente. A volte devi solo parlare con un'altra persona per trovare la soluzione.
John Hartsock,

Risposte:


113

Risposta in generale:

  1. Sì, di solito.
  2. Vedi maggiori informazioni qui
  3. Sì, poiché ognuno ha un motore di elaborazione JS diverso, tuttavia, nell'esecuzione di un test sul sito seguente, lo switch ha sempre eseguito if, elseif su un gran numero di iterazioni.

Sito di prova


1
Se vuoi un TLDR su quando usare quali condizionali qui è un collegamento diretto a un segmento dell'articolo che indirizza questo: oreilly.com/server-administration/excerpts/even-faster-we
website

2
@ Tommy Buon articolo, grazie per la condivisione. Tuttavia, l'articolo afferma che esiste una differenza di prestazioni trascurabile tra switche le if/thendichiarazioni in JS. L'articolo afferma che ciò è dovuto switchall'ottimizzazione puntuale e ai diversi modi in cui funzionano i diversi motori JS. Citazione:Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed.
Jasper,

3
C'è qualcosa di quantificabile mostrato in questa descrizione? Sembra un sacco di congetture "best practice / ottimizzazione prematura". È stato anche scritto 7 anni fa, quindi le ottimizzazioni JavaScript sono cambiate enormemente in questo momento. Nei linguaggi compilati, la differenza di prestazioni tra queste tre operazioni è "quasi mai abbastanza significativa da curare". Non preoccuparti di ottimizzare le cose che non influiranno sulle prestazioni effettive. Ottimizza la leggibilità.
Thomson Comer,

3
@ Tommy « Vedi più informazioni qui » dà 404, che cosa c'era?
LogicDaemon

2
@LogicDaemon - IIRC è stato un collegamento ad alcune caselle di testo oRielly che sono entrate in approfondite considerazioni / discussioni sulle prestazioni di JS
Tommy,

61

A volte è meglio non usare nessuno dei due. Ad esempio, in una situazione di "invio", Javascript ti consente di fare le cose in un modo completamente diverso:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

L'impostazione di ramificazioni multidirezionali creando un oggetto presenta molti vantaggi. È possibile aggiungere e rimuovere funzionalità in modo dinamico. È possibile creare la tabella di invio dai dati. Puoi esaminarlo a livello di codice. È possibile creare i gestori con altre funzioni.

C'è l'overhead aggiunto di una chiamata di funzione per arrivare all'equivalente di un "case", ma il vantaggio (quando ci sono molti casi) di una ricerca hash per trovare la funzione per un particolare tasto.


2
La tua strategia è buona e la uso spesso. Ma come indicato da @Michael Geary stackoverflow.com/a/45336805/5936119 , la variabile della mappa deve essere dichiarata al di fuori del contesto di spedizione, altrimenti verrà sempre rivalutata.
Daniel Santana,

@DanielSantana vero, ma dubito che sia significativamente costoso. In particolare, una volta analizzata una funzione inizialmente non è necessario rigenerare il codice stesso, poiché il testo è statico.
Punta il

18

La differenza di prestazioni tra a switche if...else if...elseè piccola, sostanzialmente fanno lo stesso lavoro. Una differenza tra loro che può fare la differenza è che l'espressione da testare viene valutata solo una volta switchogni tanto per ciascuno if. Se è costoso valutare l'espressione, farlo una volta è ovviamente più veloce che farlo cento volte.

La differenza nell'implementazione di quei comandi (e tutti gli script in generale) differisce abbastanza da un browser all'altro. È comune vedere differenze di prestazioni piuttosto elevate per lo stesso codice in diversi browser.

Poiché difficilmente puoi testare le prestazioni di tutto il codice in tutti i browser, dovresti cercare il codice che si adatta meglio a quello che stai facendo e cercare di ridurre la quantità di lavoro svolto anziché ottimizzare il modo in cui viene eseguito.


7
  1. Se c'è una differenza, non sarà mai abbastanza grande da essere notato.
  2. N / A
  3. No, funzionano tutti in modo identico.

Fondamentalmente, usa tutto ciò che rende il codice più leggibile. Ci sono sicuramente luoghi in cui l'uno o l'altro costrutto rende più pulito, più leggibile e più mantenibile. Questo è molto più importante che forse risparmiare qualche nanosecondo nel codice JavaScript.


5
Soprattutto in javascript, la semantica e la leggibilità (e quindi la manutenibilità) superano qualsiasi differenza di prestazioni localizzata tra if..elsee switchcausata da una combinazione unica di hardware e sistema operativo del browser.
jball,

2
Non so se sono d'accordo, potrebbe davvero essere notato se viene utilizzato in un ciclo con diciamo, un grande database, attraversando un albero ecc.
Ghoppe,

2
non sono assolutamente d'accordo. man mano che le applicazioni Web diventano sempre più complesse, questa differenza potrebbe essere significativa per l'applicazione e potrebbe cambiare in base al browser.
joshvermaire,

7
L'importante è scrivere codice pulito e gestibile. Quando viene visualizzato un problema di prestazioni - profilo. Quindi determinare quale codice correggere. Non sacrificare la manutenibilità per presunti problemi di prestazioni.
Jon Benedicto,

3
'if else if else ...' è O (n), mentre 'switch' è O (1) o O (log (n)). Come puoi onestamente affermare che la differenza non può mai essere abbastanza grande? Avere un milione di casi in switch (facilmente possibile se il codice viene generato) e lo noterai sicuramente per non dire altro.
Dragonroot,

6

Oltre alla sintassi, uno switch può essere implementato usando un albero che lo rende O(log n), mentre un if / else deve essere implementato con un O(n)approccio procedurale. Più spesso sono entrambi elaborati proceduralmente e l'unica differenza è la sintassi, e inoltre importa davvero - a meno che tu non stia digitando staticamente 10k casi di if / else comunque?


7 anni dopo ... Non vedo come sia possibile l'implementazione dell'albero, tranne nel caso di valori numerici costanti).
Ed Staub,

4

La risposta di punta suggerisce l'uso di un letterale oggetto come alternativa al switcho if/ else. Mi piace anche questo approccio, ma il codice nella risposta crea un nuovo mapoggetto ogni volta che dispatchviene chiamata la funzione:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

Se mapcontiene un numero elevato di voci, questo può creare un sovraccarico significativo. È meglio impostare la mappa delle azioni solo una volta e quindi utilizzare la mappa già creata ogni volta, ad esempio:

var actions = {
    'explode': function() {
        prepExplosive();
        if( flammable() ) issueWarning();
        doExplode();
    },

    'hibernate': function() {
        if( status() == 'sleeping' ) return;
        // ... I can't keep making this stuff up
    },
    // ...
};

function dispatch( name ) {
    var action = actions[name];
    if( action ) action();
}

3

Esiste una differenza di preformance in Javascript tra un'istruzione switch e un if ... else if .... else?

Non credo, switchè utile / breve se si desidera prevenire più if-elsecondizioni.

Il comportamento di switch e se ... altrimenti se ... è diverso nei browser? (FireFox, IE, Chrome, Opera, Safari)

Il comportamento è lo stesso in tutti i browser :)


5
switch is useful/short if you want prevent multiple if-else conditions.Sì signore, ottimo post.
NiCk Newman,

1
  1. In alcuni casi il workbenching potrebbe comportare differenze minime, ma il modo di elaborazione dipende comunque dal browser, quindi non vale la pena preoccuparsi
  2. A causa di diversi modi di elaborazione
  3. Non puoi chiamarlo un browser se il comportamento sarebbe comunque diverso

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.