Переключатель JavaScript и ifelse ifelse

Ребят, у меня пара вопросов:

  1. Есть ли разница в производительности в JavaScript между оператором switch и if...else?
  2. Если да, то почему?
  3. Отличается ли поведение switch и if...else в разных браузерах? (FireFox, IE, Chrome, Opera, Safari)

Причина, по которой я задаю этот вопрос, заключается в том, что мне кажется, что я получаю лучшую производительность от оператора switch с примерно 1000-ю случаями в Firefox.


Отредактировано. К сожалению, это не мой код. Javascript создается сервером из скомпилированной библиотеки, и у меня нет доступа к этому коду. Метод, создающий javascript, называется

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

примечание arrayofvalues - это список, разделенный запятыми.

то, что он производит,

function [name] (value) {
  if (value == [value from array index x]) {
     [action from array index x]
  }
}

Примечание: где [name] = имя, переданное в серверную функцию

Теперь я изменил вывод функции, которую нужно вставить в TextArea, написал код JavaScript для анализа функции и преобразовал его в набор операторов case.

наконец, я запускаю функцию, и она работает нормально, но производительность отличается в IE и Firefox.


person John Hartsock    schedule 27.05.2010    source источник
comment
Я бы предложил образец кода, чтобы проверить, что является оптимальным. Я имею в виду, должна быть причина, по которой ты спрашиваешь об этом, верно?   -  person jcolebrand    schedule 27.05.2010
comment
Пожалуйста, опубликуйте, чем вы занимаетесь, потому что в моем многолетнем опыте очень мало случаев, для которых я бы сказал, что инструкция switch из 100 случаев или серия if / else из 100 были хорошей идеей.   -  person Pointy    schedule 27.05.2010
comment
извините, ребята, не сотни, а тысячи условий   -  person John Hartsock    schedule 27.05.2010
comment
Всем спасибо за вклад. Но моя проблема заключалась не в разнице между состояниями if и swith. Это был код внутри оператора. +1 всем вам за вашу помощь. Приносим извинения за неудобства. Иногда вам просто нужно поговорить с другим человеком, чтобы найти решение.   -  person John Hartsock    schedule 27.05.2010


Ответы (9)


Отвечая в общих чертах:

  1. Да, обычно.
  2. Подробнее…
  3. Да, потому что каждый из них имеет свой механизм обработки JS, однако при запуске теста на сайте ниже переключатель всегда выполнял if, elseif на большом количестве итераций.

Тестовый сайт

person Tommy    schedule 27.05.2010
comment
Спасибо, Томми, ваш примерный сайт было приятно использовать при попытке определить, какая разница в производительности между if и switch. Это настолько минимально, что я пришел к выводу, что моя проблема была в другом, как я отметил в своем комментарии к моему вопросу. Спасибо за ваше время. - person John Hartsock; 27.05.2010
comment
Если вам нужен TL; DR о том, когда использовать какие условные выражения, вот прямая ссылка на сегмент статьи, посвященный этому: oreilly.com/server-administration/excerpts/even-faster-websites/ - person edhedges; 06.05.2013
comment
@Tommy Хорошая статья, спасибо, что поделились. Однако в статье говорится, что существует незначительная разница в производительности между операторами switch и if/then в JS. В статье говорится, что это связано с нечеткой switch оптимизацией и разными способами работы различных JS-движков. Цитата: Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed. - person Jasper; 17.05.2013
comment
@ Джаспер, спасибо! Но я хотел указать из статьи О'Рейли, в которой также говорится: ... операторы if обычно быстрее, чем операторы switch, когда нужно оценить только одно или два условия. Когда имеется более двух условий, и условия простые (не диапазоны), оператор switch обычно выполняется быстрее. Это связано с тем, что время, необходимое для выполнения одного условия в операторе switch, часто меньше, чем требуется для выполнения одного условия в операторе if, что делает оператор switch оптимальным только при большом количестве условий. < / я> - person Tommy; 17.05.2013
comment
@Jasper - И согласился, это не очень точный вывод, но именно поэтому я упомянул, что отвечал в общих чертах :) - person Tommy; 17.05.2013
comment
Показано ли в этом описании что-нибудь поддающееся количественной оценке? Это похоже на множество лучших практик / предположений о преждевременной оптимизации. Он также был написан 7 лет назад, поэтому оптимизация javascript за это время сильно изменилась. В скомпилированных языках разница в производительности между этими тремя операциями почти никогда не бывает достаточно значительной, чтобы беспокоиться. Не пытайтесь оптимизировать то, что не повлияет на реальную производительность. Оптимизируйте читаемость. - person Thomson Comer; 02.02.2016
comment
@ThomsonComer - это веские аргументы, но я не уверен, что с этим делать с моей точки зрения? Это не язвительный комментарий, а, скорее, просьба внести свой вклад - есть ли у вас предложение, как улучшить этот ответ 7 лет спустя? - person Tommy; 02.02.2016
comment
Что ж, впервые за это время я обнаружил, что задаю тот же вопрос, что и исходный. По прошествии семи лет я чувствую себя голосом, говорящим: «Не преждевременная оптимизация не лишена смысла». Это не тот вопрос, который вам стоит беспокоить, особенно для программистов младшего уровня. :) Ваш ответ твердый. - person Thomson Comer; 02.02.2016
comment
Тест дает мне бесконечность для некоторых случаев, вероятно, потому, что он оптимизирует пустые операторы. Я попытался сделать новую ревизию - на самом деле я добавил две, но у них нет тестовых примеров. Я не знаю, почему он не сохраняет мои изменения. Он просто говорит мне, что иногда не все тестовые примеры были сохранены или чтобы просмотреть некоторые поля, которые он не отмечает для меня каким-либо образом. Думаю, Интернету нужен новый сайт для тестирования производительности. - person Neonit; 25.04.2018
comment
@Tommy «См. Дополнительную информацию здесь» дает 404, что там было? - person LogicDaemon; 05.01.2019
comment
@LogicDaemon - IIRC - это ссылка на какое-то текстовое поле oRielly, которое затронуло некоторые подробные обсуждения / обсуждения производительности JS. - person Tommy; 08.01.2019
comment
Как видно из статистики браузера, ваше утверждение о том, что switch работает быстрее, не соответствует действительности. Измените свой ответ или контрольный показатель. - person FINDarkside; 23.01.2019
comment
Когда я смотрю на самую последнюю версию теста (версия 10 - jsperf.com / switch-case-vs-if-else / 10), после исправлений добавлены дополнительные случаи, всего 3 случая. Кажется, с 10 случаями переключатель убивает if / else, особенно в новых версиях Chrome (›70). Это показывает, что ваш пробег может варьироваться в зависимости от сценария использования, но я до сих пор не нашел случая, когда переключение было бы значительно медленнее, чем if / else (тогда как я видел противоположное по текущим показателям), поэтому я все еще уверен, что говорю да, обычно есть разница в производительности и, как правило, коммутатор работает быстрее. - person Tommy; 24.01.2019
comment
Я только что добавил один с 10 ящиками. jsperf.com/switch-case-vs-if-else/24 И похоже, что они настолько близки по производительности, что они находятся в пределах <1% друг от друга (все они отмечены как самые быстрые). Все сводится к предпочтительному синтаксису. - person etoxin; 26.08.2019
comment
странный. на самом деле он говорит, что if-else again был самым быстрым - person oldboy; 08.02.2020
comment
@oldboy - я имею в виду, что это ответ 10-летней давности, и движки JS были значительно улучшены / модифицированы / изменены за эти 10 лет. :) IMHO, это все еще зависит как от браузера, так и от функции, то есть количества случаев, объема работы по сравнению и т. Д. - person Tommy; 08.02.2020
comment
Я думаю, что единственное эмпирическое правило - просто сократить количество вычислений и повторений, чтобы повысить производительность. следовательно, switch должен быть более эффективным, если вы повторно оцениваете одно и то же значение (например, v === 1 else if v === 2 else if v === 3 else if и т. д.), вообще говоря. - person oldboy; 09.02.2020

Иногда лучше не использовать ни то, ни другое. Например, в ситуации «отправки» Javascript позволяет вам делать что-то совершенно по-другому:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

Настройка многостороннего ветвления путем создания объекта имеет множество преимуществ. Вы можете динамически добавлять и удалять функции. Вы можете создать таблицу диспетчеризации из данных. Вы можете изучить это программно. Вы можете создавать обработчики с другими функциями.

Есть дополнительные накладные расходы на вызов функции для получения эквивалента «case», но преимущество (когда много случаев) поиска по хешу для поиска функции для определенного ключа.

person Pointy    schedule 27.05.2010
comment
У вас хорошая стратегия, и я ее часто использую. Но, как указал @Michael Geary stackoverflow.com/a/45336805/5936119, переменная карты должна быть объявлена ​​вне отправки контекст, в противном случае он всегда будет повторно оцениваться. - person Daniel Santana; 24.01.2019
comment
@DanielSantana правда, но я сомневаюсь, что это значительно дорого. В частности, после первоначального синтаксического анализа функции не требуется регенерации самого кода, поскольку текст статичен. - person Pointy; 24.01.2019

Разница в производительности между switch и if...else if...else небольшая, они в основном выполняют одинаковую работу. Одно различие между ними, которое может иметь значение, заключается в том, что тестируемое выражение оценивается только один раз в switch, в то время как оно оценивается для каждого if. Если оценивать выражение дорого, то сделать это один раз, конечно, быстрее, чем сто раз.

Разница в реализации этих команд (и всего скрипта в целом) в разных браузерах сильно различается. Часто можно увидеть довольно большие различия в производительности одного и того же кода в разных браузерах.

Поскольку вы вряд ли сможете проверить производительность всего кода во всех браузерах, вам следует выбрать код, который лучше всего подходит для того, что вы делаете, и попытаться уменьшить объем выполняемой работы, а не оптимизировать ее выполнение.

person Guffa    schedule 27.05.2010

Помимо синтаксиса, переключатель может быть реализован с использованием дерева, которое делает его O(log n), в то время как if / else должен быть реализован с O(n) процедурным подходом. Чаще они оба обрабатываются процедурно, и единственная разница заключается в синтаксисе, и, кроме того, действительно ли это имеет значение - если вы все равно статически не набираете 10 тысяч случаев if / else?

person Evan Carroll    schedule 27.05.2010
comment
7 лет спустя ... Я не понимаю, как возможна реализация дерева, за исключением случая постоянных числовых значений case). - person Ed Staub; 11.02.2017
comment
3.5 года спустя ... @Ed Staub Конечно, здесь так и есть. Операторы switch работают с константами. Если уже есть числа или что-то еще, их можно перечислить, так что можно построить дерево. - person trollkotze; 09.11.2020
comment
@trollkotze Хотя наиболее распространены константы, case-предложениями могут быть любые выражения. См., Например, stackoverflow.com/questions/3463833/. - person Ed Staub; 10.11.2020
comment
О, я этого не знал. Это невозможно в C, afaik. Здесь разрешены только постоянные выражения. Поэтому я предположил, что в JS все будет так же. - person trollkotze; 11.11.2020

В ответе Pointy предлагается использовать литерал объекта в качестве альтернативы switch или _2 _ / _ 3_. Мне тоже нравится этот подход, но код в ответе создает новый объект map каждый раз, когда вызывается функция dispatch:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

Если map содержит большое количество записей, это может создать значительные накладные расходы. Лучше настроить карту действий только один раз, а затем каждый раз использовать уже созданную карту, например:

var actions = {
    'explode': function() {
        prepExplosive();
        if( flammable() ) issueWarning();
        doExplode();
    },

    'hibernate': function() {
        if( status() == 'sleeping' ) return;
        // ... I can't keep making this stuff up
    },
    // ...
};

function dispatch( name ) {
    var action = actions[name];
    if( action ) action();
}
person Michael Geary    schedule 26.07.2017

  1. Если есть разница, она никогда не будет настолько большой, чтобы ее можно было заметить.
  2. N/A
  3. Нет, все они работают одинаково.

В принципе, используйте все, что делает код наиболее читаемым. Определенно есть места, где та или иная конструкция делает ее более понятной, читаемой и удобной в обслуживании. Это гораздо важнее, чем, возможно, сэкономить несколько наносекунд в коде JavaScript.

person Jon Benedicto    schedule 27.05.2010
comment
В частности, в javascript семантика и удобочитаемость (и, следовательно, удобство обслуживания) превосходят любые локализованные различия в производительности между if..else и switch, вызванные уникальной версией компьютерного оборудования браузера и комбинацией ОС. - person jball; 27.05.2010
comment
Я не знаю, согласен ли я, это действительно может быть замечено, если он используется в цикле, например, с большой базой данных, обходом дерева и т. Д. - person ghoppe; 27.05.2010
comment
я определенно не согласен. по мере того, как веб-приложения становятся все более и более сложными, эта разница может быть значительной для приложения и может меняться в зависимости от браузеров. - person joshvermaire; 23.11.2011
comment
Важно писать чистый, поддерживаемый код. Когда замечена проблема с производительностью - профиль. Затем определите, какой код исправить. Не жертвуйте ремонтопригодностью ради предполагаемых проблем с производительностью. - person Jon Benedicto; 23.11.2011
comment
if else if else ... равно O (n), а switch - O (1) или O (log (n)). Как можно честно заявить, что разница никогда не может быть достаточно большой? Включите миллион случаев (это легко возможно, если код сгенерирован), и вы обязательно это заметите, мягко говоря. - person dragonroot; 09.05.2012
comment
@dragonroot, производительность if и switch полностью зависит от реализации движка JavaScript. Нет гарантии, что if / else равно O (n), а switch - O (1) или O (log (n)) во всех движках. Как я сказал ранее, вы не можете предполагать проблем с производительностью. Их нужно обнаруживать с помощью профилирования, особенно с помощью чего-то небольшого, например оператора if / else vs switch. - person Jon Benedicto; 09.05.2012
comment
@Jon Benedicto, switch был специально разработан, чтобы его можно было легко реализовать быстрее, чем O (n) - его синтаксис - это не просто синтаксический сахар. 'if, с другой стороны, должны были оцениваться одно за другим. - person dragonroot; 22.05.2012
comment
Если у вас есть расчеты, не зависящие от времени, чем вы уверены - выбирайте то, что вы умеете читать лучше всего. Однако, если вы просматриваете большие наборы данных или постоянно выполняете интенсивные вычисления, вам следует меньше заботиться о удобочитаемости и вместо этого искать то, что наиболее удобно для процессора. Я действительно считаю, что операторы switch во многих случаях работают быстрее, но в других не так быстро. - person Jonathan Tonge; 10.02.2013
comment
Я проголосовал против этого, потому что считаю, что обобщение, сделанное в ответ на первый вопрос, неверно. - person thatmiddleway; 18.03.2014

Есть ли разница в производительности в Javascript между оператором switch и if ... else if .... else?

Я так не думаю, switch полезно / коротко, если вы хотите предотвратить множественные if-else условия.

Отличается ли поведение switch и if ... else if ... else в разных браузерах? (FireFox, IE, Chrome, Opera, Safari)

Поведение одинаково во всех браузерах :)

person Sarfraz    schedule 27.05.2010
comment
switch is useful/short if you want prevent multiple if-else conditions. Да, сэр, отличный пост. - person NiCk Newman; 14.07.2015

  1. В некоторых случаях рабочая среда может привести к очень небольшим различиям, но способ обработки в любом случае зависит от браузера, поэтому не стоит беспокоиться
  2. Из-за разных способов обработки
  3. Вы не можете назвать это браузером, если бы поведение все равно было другим.
person Koen    schedule 27.05.2010

Оказывается, if-else, если обычно быстрее, чем switch

http://jsperf.com/switch-if-else/46

person sidonaldson    schedule 05.09.2013