Mudança de Javascript vs. if… else if… else

143

Gente, eu tenho algumas perguntas:

  1. Existe uma diferença de desempenho no JavaScript entre uma switchdeclaração e uma if...else?
  2. Se sim, por quê?
  3. O comportamento switche o comportamento são if...elsediferentes nos navegadores? (FireFox, IE, Chrome, Opera, Safari)

O motivo para fazer essa pergunta é que parece que eu obtive melhor desempenho em uma switchdeclaração com aproximadamente 1000 casos no Firefox.


Editado Infelizmente este não é o meu código, o Javascript está sendo produzido no servidor a partir de uma biblioteca compilada e não tenho acesso ao código. O método que está produzindo o javascript é chamado

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

note arrayofvaluesé uma lista separada por vírgula.

o que produz é

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

Nota: onde [name]= o nome passado para a função do lado do servidor

Agora mudei a saída da função a ser inserida em uma TextArea, escrevi algum código JavaScript para analisar a função e a converti em um conjunto de caseinstruções.

finalmente, eu executo a função e ela funciona bem, mas o desempenho difere no IE e no Firefox.

John Hartsock
fonte
1
Eu sugeriria um exemplo de código para examinar o que é ideal. Quero dizer, deve haver uma razão para você estar perguntando isso, certo?
Jcolebrand
Poste o que você está fazendo, porque há muito poucos casos em minha longa experiência para os quais eu diria que uma declaração de troca de 100 casos ou uma série de 100 partes if / else foi uma boa idéia.
Pointy 27/05
não desculpem-100s mas milhares de condições
John Hartsock
2
Todo mundo, obrigado pela contribuição. Mas meu problema não era realmente a diferença entre as declarações if e swith. Era o código em execução na declaração. +1 para todos vocês por sua ajuda. Desculpe pela inconveniência. Às vezes, você só precisa conversar com outra pessoa para encontrar a solução.
John Hartsock

Respostas:

113

Resposta em generalidades:

  1. Sim geralmente.
  2. Veja mais informações aqui
  3. Sim, porque cada um possui um mecanismo de processamento JS diferente, no entanto, ao executar um teste no site abaixo, o comutador sempre executava o if, elseif em um grande número de iterações.

Site de teste

Tommy
fonte
1
Se você quer uma TLDR de quando usar cada condicionais aqui é um link direto para um segmento no artigo endereçamento que: oreilly.com/server-administration/excerpts/even-faster-websites/...
edhedges
2
@ Tommy Bom artigo, obrigado por compartilhar. No entanto, o artigo afirma que há uma diferença insignificante de desempenho entre as instruções switche if/thenem JS. O artigo afirma que isso se deve à switchotimização irregular e às diferentes maneiras pelas quais os mecanismos JS funcionam. Citação:Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed.
Jasper
3
Há algo quantificável mostrado nesta descrição? Parece uma série de conjecturas de "melhores práticas / otimização prematura". Também foi escrito há 7 anos, então as otimizações de javascript mudaram tremendamente nesse período. Nas linguagens compiladas, a diferença de desempenho entre essas três operações "quase nunca é significativa o suficiente para atender". Não se preocupe em otimizar coisas que não afetarão o desempenho real. Otimize a legibilidade.
Thomson Comer
3
@ Tommy « Veja mais informações aqui » dá 404, o que havia?
LogicDaemon 5/01/19
2
@LogicDaemon - IIRC é era um link para alguma caixa de texto oRielly que entrou em algumas indepth JS considerações de desempenho / discussões
Tommy
61

Às vezes, é melhor usar nenhum dos dois. Por exemplo, em uma situação de "despacho", o Javascript permite fazer as coisas de uma maneira completamente diferente:

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();
}

A configuração da ramificação de várias maneiras criando um objeto tem muitas vantagens. Você pode adicionar e remover funcionalidades dinamicamente. Você pode criar a tabela de despacho a partir dos dados. Você pode examiná-lo programaticamente. Você pode criar os manipuladores com outras funções.

Há a sobrecarga adicional de uma chamada de função para chegar ao equivalente a um "caso", mas a vantagem (quando há muitos casos) de uma pesquisa de hash para encontrar a função para uma chave específica.

Pontudo
fonte
2
Sua estratégia é boa e eu a uso frequentemente. Mas, como apontado por @Michael Geary stackoverflow.com/a/45336805/5936119 , a variável do mapa deve ser declarada fora do contexto da expedição, caso contrário será sempre reavaliada.
Daniel Santana
@DanielSantana verdade, mas duvido que seja significativamente caro. Em particular, uma vez que uma função é analisada inicialmente, o próprio código não precisa ser regenerado, pois o texto é estático.
Pointy
18

A diferença de desempenho entre a switche if...else if...elseé pequena, eles basicamente fazem o mesmo trabalho. Uma diferença entre eles que pode fazer a diferença é que a expressão a ser testada é avaliada apenas de vez em switchquando é avaliada para cada uma if. Se é caro avaliar a expressão, fazê-lo uma vez é obviamente mais rápido do que fazê-lo cem vezes.

A diferença na implementação desses comandos (e todos os scripts em geral) difere bastante entre os navegadores. É comum ver grandes diferenças de desempenho para o mesmo código em diferentes navegadores.

Como você dificilmente pode testar o desempenho de todo o código em todos os navegadores, opte pelo código que melhor se adequa ao que está fazendo e tente reduzir a quantidade de trabalho realizado, em vez de otimizar o desempenho.

Guffa
fonte
7
  1. Se houver uma diferença, ela nunca será grande o suficiente para ser notada.
  2. N / D
  3. Não, todos eles funcionam de forma idêntica.

Basicamente, use o que torna o código mais legível. Definitivamente, existem lugares onde uma ou outra construção contribui para uma limpeza, mais legibilidade e manutenção. Isso é muito mais importante que talvez salvando alguns nanossegundos no código JavaScript.

Jon Benedicto
fonte
5
Especialmente em javascript, a semântica e a legibilidade (e, portanto, a capacidade de manutenção) superam quaisquer diferenças de desempenho localizadas entre if..elsee switchcausadas por uma combinação exclusiva de hardware e sistema operacional da versão do navegador e do sistema operacional.
jball
2
Eu não sei se eu concordar, ele pode realmente ser notado se ele é usado em um loop com digamos, um grande banco de dados, atravessando uma árvore etc.
ghoppe
2
Eu definitivamente discordo. À medida que os aplicativos da Web se tornam cada vez mais complexos, essa diferença pode ser significativa para o aplicativo e pode mudar dependendo dos navegadores.
joshvermaire
7
O importante é escrever um código limpo e sustentável. Quando um problema de desempenho é visto - perfil. Em seguida, determine qual código corrigir. Não sacrifique a capacidade de manutenção por problemas de desempenho assumidos.
Jon Benedicto
3
'if else if else ...' é O (n), enquanto 'switch' é O (1) ou O (log (n)). Como você pode afirmar honestamente que a diferença nunca pode ser grande o suficiente? Tenha um milhão de casos em troca (facilmente possível se o código for gerado) e você definitivamente notará isso para dizer o mínimo.
dragonroot
6

Diferente da sintaxe, um switch pode ser implementado usando uma árvore que o cria O(log n), enquanto um if / else deve ser implementado com uma O(n)abordagem procedural. Na maioria das vezes, eles são processados ​​processualmente e a única diferença é a sintaxe. Além disso, isso realmente importa - a menos que você esteja digitando estaticamente 10 mil casos de if / else, afinal?

Evan Carroll
fonte
7 anos depois ... Não vejo como a implementação em árvore é possível, exceto no caso de valores numéricos constantes de casos).
Ed Staub
4

A resposta de Pointy sugere o uso de um objeto literal como uma alternativa a switchou if/ else. Também gosto dessa abordagem, mas o código na resposta cria um novo mapobjeto toda vez que a dispatchfunção é chamada:

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();
}

Se mapcontiver um grande número de entradas, isso poderá criar uma sobrecarga significativa. É melhor configurar o mapa de ação apenas uma vez e depois usar o mapa já criado a cada vez, por exemplo:

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();
}
Michael Geary
fonte
3

Existe uma diferença de pré-desempenho em Javascript entre uma instrução switch e uma if ... else if .... else?

Eu acho que não, switché útil / curto se você quiser evitar várias if-elsecondições.

O comportamento do switch e se ... else se ... else é diferente nos navegadores? (FireFox, IE, Chrome, Opera, Safari)

O comportamento é o mesmo em todos os navegadores :)

Sarfraz
fonte
5
switch is useful/short if you want prevent multiple if-else conditions.Sim senhor, ótimo post.
NiCk Newman
1
  1. O ambiente de trabalho pode resultar em algumas diferenças muito pequenas em alguns casos, mas a maneira de processar depende do navegador de qualquer maneira, portanto, não vale a pena incomodar
  2. Devido a diferentes formas de processamento
  3. Você não pode chamá-lo de navegador se o comportamento for diferente de qualquer maneira
Koen
fonte