Cuando miré las soluciones en las otras respuestas, vi algunas cosas que sé que son malas para el rendimiento. Iba a ponerlos en un comentario, pero pensé que era mejor compararlo y compartir los resultados. Puedes probarlo tú mismo . A continuación se muestran mis resultados (ymmv) normalizados después de la operación más rápida en cada navegador (multiplique el tiempo 1.0 con el valor normalizado para obtener el tiempo absoluto en ms).
Chrome Firefox Opera MSIE Safari Node
-------------------------------------------------- -----------------
1.0 tiempo 37ms 73ms 68ms 184ms 73ms 21ms
si es inmediato 1.0 1.0 1.0 2.6 1.0 1.0
si indirecto 1.2 1.8 3.3 3.8 2.6 1.0
cambio inmediato 2.0 1.1 2.0 1.0 2.8 1.3
rango de conmutación 38.1 10.6 2.6 7.3 20.9 10.4
rango de conmutación2 31.9 8.3 2.0 4.5 9.5 6.9
switch-indirecta-matriz 35.2 9.6 4.2 5.5 10.7 8.6
matriz-interruptor-lineal 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
La prueba se realizó en Windows 7 de 32 bits con las siguientes versiones: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 . Node se ejecutó en una caja Linux de 64 bits porque la resolución del temporizador en Node.js para Windows fue de 10 ms en lugar de 1 ms.
si es inmediato
Este es el más rápido en todos los entornos probados, excepto en ... drumroll MSIE! (sorpresa sorpresa). Esta es la forma recomendada de implementarlo.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
si indirecto
Esta es una variante de switch-indirect-array
pero con if
declaraciones en su lugar y funciona mucho más rápido que switch-indirect-array
en casi todos los entornos probados.
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
cambio inmediato
Esto es bastante rápido en todos los entornos probados, y en realidad es el más rápido en MSIE. Funciona cuando puede hacer un cálculo para obtener un índice.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
rango de conmutación
Esto es aproximadamente de 6 a 40 veces más lento que el más rápido en todos los entornos probados, excepto Opera, donde dura aproximadamente una vez y media más. Es lento porque el motor tiene que comparar el valor dos veces para cada caso. Sorprendentemente, Chrome tarda casi 40 veces más en completar esto en comparación con la operación más rápida en Chrome, mientras que MSIE solo tarda 6 veces más. Pero la diferencia de tiempo real fue de solo 74 ms a favor de MSIE a 1337 ms (!).
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 es una variante de switch-range
pero con solo una comparación por caso y, por lo tanto, más rápida, pero aún muy lenta, excepto en Opera. El orden de la declaración del caso es importante ya que el motor probará cada caso en el orden del código fuente ECMAScript262: 5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
conmutador-matriz-indirecta
En esta variante, los rangos se almacenan en una matriz. Esto es lento en todos los entornos probados y muy lento en 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-linear-search
Esta es una combinación de una búsqueda lineal de valores en una matriz y la instrucción de cambio con valores fijos. La razón por la que uno podría querer usar esto es cuando los valores no se conocen hasta el tiempo de ejecución. Es lento en todos los entornos probados y tarda casi 10 veces más en 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;
}
matriz-interruptor-binario
Esta es una variante de array-linear-switch
pero con una búsqueda binaria. Lamentablemente es más lento que la búsqueda lineal. No sé si es mi implementación o si la búsqueda lineal está más optimizada. También podría ser que el espacio de teclas sea demasiado pequeño.
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;
}
Conclusión
Si el rendimiento es importante, use if
declaraciones o switch
con valores inmediatos.