Когда я посмотрел на решения в других ответах, я увидел некоторые вещи, которые, как я знаю, плохо влияют на производительность. Я собирался поместить их в комментарий, но я подумал, что было бы лучше сравнить его и поделиться результатами. Вы можете проверить это сами . Ниже приведены мои результаты (ymmv), нормализованные после самой быстрой операции в каждом браузере (умножьте 1,0 раз на нормализованное значение, чтобы получить абсолютное время в мс).
Chrome Firefox Opera MSIE Safari Node
-------------------------------------------------- -----------------
1,0 время 37мс 73мс 68мс 184мс 73мс 21мс
если немедленный 1,0 1,0 1,0 2,6 1,0 1,0
если косвенный 1,2 1,8 3,3 3,8 2,6 1,0
switch-немедленный 2.0 1.1 2.0 1.0 2.8 1.3
диапазон переключения 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
переключатель-косвенный-массив 35,2 9,6 4,2 5,5 10,7 8,6
массив-линейный переключатель 3,6 4,1 4,5 10,0 4,7 2,7
массив-бинарный переключатель 7,8 6,7 9,5 16,0 15,0 4,9
Тест проводился в Windows 7 32bit с следующими версиями: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 . Узел был запущен на 64-битной системе Linux, поскольку разрешение таймера в Node.js для Windows составляло 10 мс, а не 1 мс.
если немедленное
Это самая быстрая во всех протестированных средах, за исключением ... барабанной дроби MSIE! (Сюрприз Сюрприз). Это рекомендуемый способ его реализации.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
если косвенный
Это вариант, switch-indirect-array
но с if
вместо -statements и работает намного быстрее, чем switch-indirect-array
почти во всех протестированных средах.
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
включение немедленное
Это довольно быстро во всех протестированных средах и на самом деле самый быстрый в MSIE. Это работает, когда вы можете сделать расчет, чтобы получить индекс.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
автоматическое включение фар
Это примерно в 6-40 раз медленнее, чем самая быстрая во всех протестированных средах, за исключением Opera, где она занимает примерно полтора раза. Это медленно, потому что двигатель должен сравнить значение дважды для каждого случая. Удивительно, но для выполнения этого Chrome требуется почти 40 раз больше времени по сравнению с самой быстрой операцией в Chrome, а MSIE - всего в 6 раз дольше. Но фактическая разница во времени составляла только 74 мс в пользу MSIE при 1337 мс (!).
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;
}
включение range2
Это вариант, switch-range
но с одним сравнением в каждом случае, поэтому он быстрее, но все еще очень медленный, за исключением Opera. Порядок оператора case важен, так как механизм будет проверять каждый случай в порядке исходного кода. ECMAScript262: 5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
включение косвенного массива
В этом варианте диапазоны хранятся в массиве. Это медленно во всех протестированных средах и очень медленно в 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;
}
массив линейного поиска
Это комбинация линейного поиска значений в массиве и оператора switch с фиксированными значениями. Причина, по которой можно использовать это, заключается в том, что значения неизвестны до времени выполнения. Он медленный в каждой тестируемой среде и занимает почти в 10 раз больше времени в 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-linear-switch
но с бинарным поиском. К сожалению, это медленнее, чем линейный поиск. Я не знаю, является ли это моей реализацией или линейный поиск более оптимизирован. Возможно также, что пространство клавиш слишком маленькое.
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;
}
Вывод
Если важна производительность, используйте if
-statements или switch
с непосредственными значениями.