Quando ho esaminato le soluzioni nelle altre risposte, ho visto alcune cose che so essere dannose per le prestazioni. Li avrei messi in un commento, ma ho pensato che fosse meglio confrontarlo e condividere i risultati. Puoi provarlo tu stesso . Di seguito sono riportati i miei risultati (ymmv) normalizzati dopo l'operazione più veloce in ciascun browser (moltiplicare il tempo 1.0 per il valore normalizzato per ottenere il tempo assoluto in ms).
Chrome Firefox Opera MSIE Safari Node
-------------------------------------------------- -----------------
1.0 tempo 37ms 73ms 68ms 184ms 73ms 21ms
if-immediate 1.0 1.0 1.0 2.6 1.0 1.0
if-indiretto 1,2 1,8 3,3 3,8 2,6 1,0
switch-immediate 2.0 1.1 2.0 1.0 2.8 1.3
campo di commutazione 38,1 10,6 2,6 7,3 20,9 10,4
campo di commutazione2 31,9 8,3 2,0 4,5 9,5 6,9
switch-indiretto-array 35,2 9,6 4,2 5,5 10,7 8,6
array-linear-switch 3.6 4.1 4.5 10.0 4.7 2.7
array-binary-switch 7.8 6.7 9.5 16.0 15.0 4.9
Test eseguito su Windows 7 a 32 bit con le seguenti versioni: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 . Il nodo è stato eseguito su un box Linux a 64 bit perché la risoluzione del timer su Node.js per Windows era di 10 ms anziché 1 ms.
se-immediata
Questo è il più veloce in tutti gli ambienti testati, tranne in ... rullo di tamburi MSIE! (sorpresa sorpresa). Questo è il modo raccomandato per implementarlo.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
se-indiretta
Questa è una variante switch-indirect-array
ma con if
-statements invece e funziona molto più velocemente rispetto switch-indirect-array
a quasi tutti gli ambienti testati.
values=[
1000, 2000, ... 30000
];
if (val < values[0]) { /* do something */ } else
if (val < values[1]) { /* do something */ } else
...
if (val < values[29]) { /* do something */ } else
switch-immediata
Questo è piuttosto veloce in tutti gli ambienti testati e in realtà il più veloce in MSIE. Funziona quando puoi fare un calcolo per ottenere un indice.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
switch-gamma
Questo è circa da 6 a 40 volte più lento del più veloce in tutti gli ambienti testati ad eccezione di Opera, dove impiega circa una volta e mezza il tempo. È lento perché il motore deve confrontare il valore due volte per ogni caso. Sorprendentemente, Chrome richiede quasi 40 volte di più per completarlo rispetto all'operazione più veloce in Chrome, mentre MSIE richiede solo 6 volte di più. Ma la differenza temporale effettiva era solo 74ms a favore di MSIE a 1337ms (!).
switch (true) {
case (0 <= val && val < 1000): /* do something */ break;
case (1000 <= val && val < 2000): /* do something */ break;
...
case (29000 <= val && val < 30000): /* do something */ break;
}
switch-intervallo2
Questa è una variante switch-range
ma con un solo confronto per caso e quindi più veloce, ma comunque molto lenta tranne che in Opera. L'ordine dell'istruzione case è importante poiché il motore testerà ogni caso nell'ordine ECMAScript262: 5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
switch-indiretta-array
In questa variante gli intervalli sono memorizzati in un array. Questo è lento in tutti gli ambienti testati e molto lento in Chrome.
values=[1000, 2000 ... 29000, 30000];
switch(true) {
case (val < values[0]): /* do something */ break;
case (val < values[1]): /* do something */ break;
...
case (val < values[29]): /* do something */ break;
}
array-lineare di ricerca
Questa è una combinazione di una ricerca lineare di valori in un array e l'istruzione switch con valori fissi. Il motivo per cui uno potrebbe voler usare questo è quando i valori non sono noti fino al runtime. È lento in ogni ambiente testato e impiega quasi 10 volte di più in MSIE.
values=[1000, 2000 ... 29000, 30000];
for (sidx=0, slen=values.length; sidx < slen; ++sidx) {
if (val < values[sidx]) break;
}
switch (sidx) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
array-binario-switch
Questa è una variante di array-linear-switch
ma con una ricerca binaria. Sfortunatamente è più lento della ricerca lineare. Non so se è la mia implementazione o se la ricerca lineare è più ottimizzata. Potrebbe anche essere che lo spazio dei tasti sia troppo piccolo.
values=[0, 1000, 2000 ... 29000, 30000];
while(range) {
range = Math.floor( (smax - smin) / 2 );
sidx = smin + range;
if ( val < values[sidx] ) { smax = sidx; } else { smin = sidx; }
}
switch (sidx) {
case 0: /* do something */ break;
...
case 29: /* do something */ break;
}
Conclusione
Se le prestazioni sono importanti, utilizzare if
-statements o switch
con valori immediati.