Quand j'ai regardé les solutions dans les autres réponses, j'ai vu des choses que je sais néfastes pour les performances. J'allais les mettre dans un commentaire mais j'ai pensé qu'il valait mieux le comparer et partager les résultats. Vous pouvez le tester vous-même . Voici mes résultats (ymmv) normalisés après l'opération la plus rapide dans chaque navigateur (multipliez le temps 1.0 par la valeur normalisée pour obtenir le temps absolu en ms).
Nœud Safari Firefox Firefox MSIE
-------------------------------------------------- -----------------
1.0 temps 37ms 73ms 68ms 184ms 73ms 21ms
si immédiat 1,0 1,0 1,0 2,6 1,0 1,0
si-indirect 1,2 1,8 3,3 3,8 2,6 1,0
commutation immédiate 2,0 1,1 2,0 1,0 2,8 1,3
plage de commutation 38,1 10,6 2,6 7,3 20,9 10,4
gamme de commutateurs2 31,9 8,3 2,0 4,5 9,5 6,9
switch-indirect-array 35,2 9,6 4,2 5,5 10,7 8,6
Commutateur linéaire de réseau 3,6 4,1 4,5 10,0 4,7 2,7
commutateur binaire de matrice 7,8 6,7 9,5 16,0 15,0 4,9
Testez où effectué sur Windows 7 32 bits avec les versions suivantes: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 . Node a été exécuté sur une boîte Linux 64 bits car la résolution du minuteur sur Node.js pour Windows était de 10 ms au lieu de 1 ms.
si-immédiat
C'est le plus rapide dans tous les environnements testés, sauf dans ... drumroll MSIE! (surprise Surprise). Il s'agit de la méthode recommandée pour l'implémenter.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
si-indirect
Il s'agit d'une variante de switch-indirect-array
mais avec des if
instructions à la place et qui fonctionne beaucoup plus rapidement que switch-indirect-array
dans presque tous les environnements testés.
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
interrupteur immédiat
C'est assez rapide dans tous les environnements testés, et en fait le plus rapide dans MSIE. Cela fonctionne lorsque vous pouvez faire un calcul pour obtenir un index.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
gamme de commutateurs
C'est environ 6 à 40 fois plus lent que le plus rapide dans tous les environnements testés, sauf pour Opera où cela prend environ une fois et demie plus de temps. C'est lent car le moteur doit comparer la valeur deux fois pour chaque cas. Étonnamment, cela prend presque 40 fois plus de temps à Chrome pour terminer cette opération que l'opération la plus rapide de Chrome, tandis que MSIE ne prend que 6 fois plus de temps. Mais le décalage horaire réel n'était que de 74 ms en faveur de MSIE à 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;
}
gamme de commutateurs2
Il s'agit d'une variante de switch-range
mais avec une seule comparaison par cas et donc plus rapide, mais toujours très lente sauf dans Opera. L'ordre de la déclaration de cas est important car le moteur testera chaque cas dans l'ordre du code source 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-indirect-array
Dans cette variante, les plages sont stockées dans un tableau. C'est lent dans tous les environnements testés et très lent dans 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;
}
tableau-recherche linéaire
Il s'agit d'une combinaison d'une recherche linéaire de valeurs dans un tableau et de l'instruction switch avec des valeurs fixes. La raison pour laquelle vous voudrez peut-être l'utiliser est que les valeurs ne sont pas connues avant l'exécution. Il est lent dans tous les environnements testés et prend près de 10 fois plus de temps dans 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;
}
tableau-commutateur-binaire
Il s'agit d'une variante de array-linear-switch
mais avec une recherche binaire. Malheureusement, elle est plus lente que la recherche linéaire. Je ne sais pas si c'est mon implémentation ou si la recherche linéaire est plus optimisée. Il se peut également que l'espace de clés soit trop petit.
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;
}
Conclusion
Si les performances sont importantes, utilisez if
-statements ou switch
avec des valeurs immédiates.