Когда я посмотрел на решения в других ответах, я увидел некоторые вещи, которые, как я знаю, плохо влияют на производительность.Я собирался поместить их в комментарий, но я подумал, что было бы лучше сравнить его и поделиться результатами.Вы можете проверить это самостоятельно .Ниже приведены мои результаты (ymmv), нормализованные после самой быстрой операции в каждом браузере (умножьте 1,0 раз на нормализованное значение, чтобы получить абсолютное время в мс).
Chrome Firefox Opera MSIE Safari Node
-------------------------------------------------------------------
1.0 time 37ms 73ms 68ms 184ms 73ms 21ms
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
switch-range 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
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
Тест, выполненный в Windows 7 32bit сследующие версии: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.10,7 . Узел был запущен на 64-битном компьютере с Linux, поскольку разрешение таймера в Node.js для Windows составляло 10 мс вместо 1 мс.
if-немедленный
Это самый быстрый ввсе протестированные среды, кроме ... барабанная дробь MSIE!(Сюрприз Сюрприз).Это рекомендуемый способ его реализации.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
if-косвенный
Это вариант switch-indirect-array
, но с if
-условиями вместо этого и работает намного быстрее, чем 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
switch-немедленный
Это довольно быстро во всех протестированных средах и на самом деле самый быстрый в 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;
}
switch-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;
}
switch-косвенный-массив
InВ этом варианте диапазоны хранятся в массиве.Это медленно во всех протестированных средах и очень медленно в 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
Это комбинация линейного поиска значений в массиве и переключателязаявление с фиксированными значениями.Причина, по которой можно использовать это, заключается в том, что значения неизвестны до времени выполнения.Он медленный в каждой тестируемой среде и занимает почти в 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-binary-switch
Это вариант 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
-статизмы или switch
с непосредственными значениями.