Quando analisei as soluções nas outras respostas, vi algumas coisas que sei que são ruins para o desempenho. Eu os colocaria em um comentário, mas achei melhor compará-lo e compartilhar os resultados. Você pode testar você mesmo . Abaixo estão meus resultados (ymmv) normalizados após a operação mais rápida em cada navegador (multiplique o tempo 1,0 com o valor normalizado para obter o tempo absoluto em ms).
Nó Safari do Opera Firefox do MSIE do Chrome
-------------------------------------------------- -----------------
1.0 tempo 37ms 73ms 68ms 184ms 73ms 21ms
if-imediato 1,0 1,0 1,0 2,6 1,0 1,0
se indireto 1,2 1,8 3,3 3,8 2,6 1,0
mudança imediata 2,0 1,1 2,0 1,0 2,8 1,3
faixa de comutação 38,1 10,6 2,6 7,3 20,9 10,4
switch-range2 31,9 8,3 2,0 4,5 9,5 6,9
matriz indireta de comutação 35,2 9,6 4,2 5,5 10,7 8,6
comutador linear de matriz 3,6 4,1 4,5 10,0 4,7 2,7
comutador binário da matriz 7,8 6,7 9,5 16,0 15,0 4,9
Teste onde foi executado no Windows 7 32bit com as seguintes versões: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 . O nó foi executado em uma caixa de 64 bits do Linux porque a resolução do timer no Node.js para Windows era 10ms em vez de 1ms.
se imediato
Este é o mais rápido em todos os ambientes testados, exceto em ... drumroll MSIE! (surpresa surpresa). Esta é a maneira recomendada de implementá-lo.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
se indireto
Essa é uma variante, switch-indirect-array
mas com, em if
vez disso, e executa muito mais rapidamente do que switch-indirect-array
em quase todos os ambientes testados.
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
interruptor imediato
Isso é muito rápido em todos os ambientes testados e, na verdade, o mais rápido no MSIE. Funciona quando você pode fazer um cálculo para obter um índice.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
switch-range
Isso é cerca de 6 a 40 vezes mais lento que o mais rápido em todos os ambientes testados, exceto no Opera, onde leva cerca de uma vez e meia o tempo. É lento porque o mecanismo precisa comparar o valor duas vezes para cada caso. Surpreendentemente, o Chrome leva quase 40 vezes mais tempo para concluir isso em comparação com a operação mais rápida do Chrome, enquanto o MSIE leva apenas 6 vezes mais. Mas a diferença horária real foi de apenas 74ms a favor do MSIE em 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-range2
Esta é uma variante de, switch-range
mas com apenas uma comparação por caso e, portanto, mais rápida, mas ainda muito lenta, exceto no Opera. A ordem da instrução do caso é importante, pois o mecanismo testará cada caso na ordem do código-fonte ECMAScript262: 5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
matriz indireta
Nesta variante, os intervalos são armazenados em um array. Isso é lento em todos os ambientes testados e muito lento no 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;
}
pesquisa linear de matriz
Essa é uma combinação de uma pesquisa linear de valores em uma matriz e a instrução switch com valores fixos. O motivo pelo qual alguém pode querer usar isso é quando os valores não são conhecidos até o tempo de execução. É lento em todos os ambientes testados e leva quase 10 vezes mais tempo no 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;
}
comutador binário de matriz
Esta é uma variante de, array-linear-switch
mas com uma pesquisa binária. Infelizmente, é mais lento que a pesquisa linear. Não sei se é minha implementação ou se a pesquisa linear é mais otimizada. Também pode ser que o espaço da chave seja pequeno.
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;
}
Conclusão
Se o desempenho for importante, use if
-statements ou switch
com valores imediatos.