Indiquer la déclaration pour plus de / moins que

Alors je veux utiliser une déclaration de commutation comme celle-ci:

switch (scrollLeft) { case (<1000): //do stuff break; case (>1000 && <2000): //do stuff break; } 

Maintenant, je sais que l'une de ces déclarations ( <1000 ) ou ( >1000 && <2000 ) ne fonctionnera pas (pour différentes raisons, évidemment). Ce que je demande est le moyen le plus efficace de faire exactement cela. Je déteste utiliser 30 instructions if , alors je préférerais utiliser la syntaxe de l'interrupteur. Y a-t-il quelque chose que je puisse faire?

Lorsque j'ai examiné les solutions dans les autres réponses, j'ai vu des essais que je sais où les performances sont mauvaises. J'allais le mettre dans un commentaire, mais je pensais 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).

                     Chrome Firefox Opera MSIE Safari Node
 -------------------------------------------------- -----------------
 1,0 fois 37 ms 73 ms 68 ms 184 ms 73 ms 21 ms
 If-immediate 1.0 1.0 1.0 2.6 1.0 1.0
 If-indirect 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
 Gamme 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
 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 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 . Le nœud a été exécuté sur une boîte Linux 64 bits car la résolution de la minuterie sur Node.js pour Windows était de 10 ms au lieu de 1 ms.

Si-immédiate

C'est le plus rapide dans tous les environnements testés, sauf dans … drumroll MSIE! (surprise Surprise). C'est la manière recommandée de 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 if -statements à la place et 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 

Commutateur immédiate

C'est assez rapide dans tous les environnements testés, et en fait le plus rapide dans MSIE. Cela fonctionne lorsque vous pouvez effectuer 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; } 

Switch-range

Il s'agit d'environ 6 à 40 fois plus lent que le plus rapide dans tous les environnements testés, à l'exception d'Opera, où il faut environ une fois et demie. Il est lent parce que le moteur doit comparer la valeur deux fois pour chaque cas. De manière surprenante, Chrome nécessite presque 40 fois plus pour compléter cela par rapport au fonctionnement le plus rapide de Chrome, alors que MSIE ne prend que 6 fois plus longtemps. Mais la différence de temps réelle n'était que de 74ms en faveur de MSIE à 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

Il s'agit d'une variante de la switch-range 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 de 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

Ceci est une combinaison d'une recherche linéaire de valeurs dans un tableau, et l'instruction de commutation avec des valeurs fixes. La raison pour laquelle on pourrait vouloir utiliser cela est lorsque les valeurs ne sont pas connues jusqu'à l'exécution. Il est lent dans chaque environnement testé et prend presque 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; } 

Array-binary-switch

Il s'agit d'une variante de array-linear-switch mais avec une recherche binaire. Malheureusement, il est plus lent que la recherche linéaire. Je ne sais pas si c'est ma mise en œuvre ou si la recherche linéaire est plus optimisée. Il se pourrait aussi que l'espace clé soit 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 la performance est importante, utilisez if déclarations ou switch avec des valeurs immédiates.

Une alternative:

 var scrollleft = 1000; switch (true) { case (scrollleft > 1000): alert('gt'); break; case (scrollleft <= 1000): alert('lt'); break; } 

Demo: http://jsfiddle.net/UWYzr/

 switch (scrollLeft/1000) { case 0: // (<1000) //do stuff break; case 1: // (>=1000 && <2000) //do stuff; break; } 

Fonctionne uniquement si vous avez des étapes régulières …

EDIT: puisque cette solution continue de se lancer, je dois conseiller que la solution de mofolo soit mieux

Vous pouvez créer un objet personnalisé avec les critères et la fonction correspondant aux critères

 var rules = [{ lowerLimit: 0, upperLimit: 1000, action: function1 }, { lowerLimit: 1000, upperLimit: 2000, action: function2 }, { lowerLimit: 2000, upperLimit: 3000, action: function3 }]; 

Définissez les fonctions pour ce que vous voulez faire dans ces cas (définissez function1, function2 etc.)

Et "évaluer" les règles

 function applyRules(scrollLeft) { for(var i=0; i>rules.length; i++) { var oneRule = rules[i]; if(scrollLeft > oneRule.lowerLimit && scrollLeft < oneRule.upperLimit) { oneRule.action(); } } } 

Remarque

Je déteste utiliser 30 déclarations si

Plusieurs fois, si les instructions sont plus faciles à lire et à conserver. Je recommanderais ce qui précède seulement lorsque vous avez beaucoup de conditions et une possibilité de beaucoup de croissance à l'avenir.

Mettre à jour
Comme @Brad a souligné dans les commentaires, si les conditions sont mutuellement exclusives (un seul d'entre elles peut être vrai à la fois), vérifier que la limite supérieure devrait être suffisante:

 if(scrollLeft < oneRule.upperLimit) 

À condition que les conditions soient définies par ordre croissant (premièrement la plus basse, 0 to 1000 , puis 1000 to 2000 par exemple)

Non testé et incertain si cela fonctionnera, mais pourquoi ne pas faire quelques if statements avant, pour définir des variables pour l' switch statement .

 var small, big; if(scrollLeft < 1000){ //add some token to the page //call it small } switch (//reference token/) { case (small): //do stuff break; case (big): //do stuff; break; } 

Que faites-vous exactement dans //do stuff ?

Vous pouvez être en mesure de faire quelque chose comme:

 (scrollLeft < 1000) ? //do stuff : (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff : (scrollLeft > 2000) ? //do stuff : //etc. 

Dans mon cas (codage par couleur d'un pourcentage, rien de critique pour la performance), j'ai rapidement écrit ceci:

 function findColor(progress) { const thresholds = [30, 60]; const colors = ["#90B451", "#F9A92F", "#90B451"]; return colors.find((col, index) => { return index >= thresholds.length || progress < thresholds[index]; }); } 

C'est une autre option:

  switch (true) { case (value > 100): //do stuff break; case (value <= 100)&&(value > 75): //do stuff break; case (value < 50): //do stuff break; } 

Mise à jour de la réponse acceptée (ne peut pas encore commenter). Du 1/12/16 en utilisant la demo jsfiddle en chrome, switch-immediate est la solution la plus rapide.

Résultats: résolution du temps: 1.33

  25ms "if-immediate" 150878146 29ms "if-indirect" 150878146 24ms "switch-immediate" 150878146 128ms "switch-range" 150878146 45ms "switch-range2" 150878146 47ms "switch-indirect-array" 150878146 43ms "array-linear-switch" 150878146 72ms "array-binary-switch" 150878146 

Fini

  1.04 ( 25ms) if-immediate 1.21 ( 29ms) if-indirect 1.00 ( 24ms) switch-immediate 5.33 ( 128ms) switch-range 1.88 ( 45ms) switch-range2 1.96 ( 47ms) switch-indirect-array 1.79 ( 43ms) array-linear-switch 3.00 ( 72ms) array-binary-switch