Javascript cambiar vs. if ... else if ... else

143

Chicos, tengo un par de preguntas:

  1. ¿Hay una diferencia de rendimiento en JavaScript entre una switchdeclaración y una if...else?
  2. Si es así, ¿por qué?
  3. Es el comportamiento de switchy if...elsediferentes a través de los navegadores? (Firefox, IE, Chrome, Opera, Safari)

La razón para hacer esta pregunta es que parece que obtengo un mejor rendimiento en una switchdeclaración con aproximadamente 1000 casos en Firefox.


Editado Desafortunadamente este no es mi código, el Javascript se está produciendo en el servidor desde una biblioteca compilada y no tengo acceso al código. El método que produce el javascript se llama

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

note arrayofvalueses una lista separada por comas.

lo que produce es

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

Nota: where [name]= el nombre pasado a la función del servidor

Ahora cambié la salida de la función para insertarla en un TextArea, escribí un código JavaScript para analizar la función y la convertí en un conjunto de casedeclaraciones.

Finalmente ejecuto la función y funciona bien, pero el rendimiento difiere en IE y Firefox.

John Hartsock
fuente
1
Sugeriría una muestra de código para examinar lo que es óptimo. Quiero decir, tiene que haber una razón por la que preguntas esto, ¿verdad?
jcolebrand
Publique lo que está haciendo, porque hay muy pocos casos en mi larga experiencia para los cuales diría que una declaración de cambio de 100 casos o una serie de 100 partes si / de otra manera fue una buena idea.
Puntiagudo
no lo siento chicos 100s pero miles de condiciones
John Hartsock
2
Todos, gracias por el aporte. Pero mi problema no era en realidad la diferencia entre las declaraciones if y swith. Era el código que se ejecutaba dentro de la declaración. +1 a todos ustedes por su ayuda. Perdón por la molestia. A veces solo necesitas hablar con otra persona para encontrar la solución.
John Hartsock

Respuestas:

113

Respondiendo en generalidades:

  1. Si, por lo general.
  2. Ver más información aquí
  3. Sí, debido a que cada uno tiene un motor de procesamiento JS diferente, sin embargo, al ejecutar una prueba en el sitio a continuación, el conmutador siempre realizó el if, elseif en un gran número de iteraciones.

Sitio de prueba

Tommy
fuente
1
Si desea un TLDR de cuándo usar qué condicionales aquí hay un enlace directo a un segmento en el artículo que aborda eso: oreilly.com/server-administration/excerpts/even-faster-websites/…
edhedges
2
@Tommy Buen artículo, gracias por compartir. Sin embargo, el artículo establece que hay una diferencia de rendimiento insignificante entre switchy las if/thendeclaraciones en JS. El artículo establece que esto se debe a la switchoptimización irregular y a las diferentes formas en que funcionan los diferentes motores JS. Cita:Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed.
Jasper
3
¿Se muestra algo cuantificable en esta descripción? Se lee como muchas conjeturas de "mejores prácticas / optimización prematura". También se escribió hace 7 años, por lo que las optimizaciones de JavaScript han cambiado enormemente en este momento. En los lenguajes compilados, la diferencia de rendimiento entre estas tres operaciones "casi nunca es lo suficientemente significativa como para importar". No se moleste en optimizar las cosas que no afectarán el rendimiento real. Optimizar la legibilidad.
Thomson Comer
3
@Tommy « Ver más información aquí » da 404, ¿qué había allí?
LogicDaemon
2
@LogicDaemon - IIRC es un enlace a un cuadro de texto único que se metió en algunas consideraciones / discusiones de rendimiento de JS en profundidad
Tommy
61

A veces es mejor no usar ninguno. Por ejemplo, en una situación de "despacho", Javascript le permite hacer las cosas de una manera 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();
}

La configuración de la ramificación multidireccional mediante la creación de un objeto tiene muchas ventajas. Puede agregar y eliminar funcionalidades dinámicamente. Puede crear la tabla de despacho a partir de datos. Puedes examinarlo mediante programación. Puede construir los manejadores con otras funciones.

Existe la sobrecarga adicional de una llamada de función para llegar al equivalente de un "caso", pero la ventaja (cuando hay muchos casos) de una búsqueda hash para encontrar la función para una tecla en particular.

Puntiagudo
fuente
2
Tu estrategia es buena y la uso con frecuencia. Pero como lo señaló @Michael Geary stackoverflow.com/a/45336805/5936119 , la variable del mapa debe declararse fuera del contexto de envío; de lo contrario, siempre se volverá a evaluar.
Daniel Santana
@DanielSantana es cierto, pero dudo que sea significativamente costoso. En particular, una vez que una función se analiza inicialmente, el código en sí no necesita ser regenerado, ya que el texto es estático.
Puntiagudo
18

La diferencia de rendimiento entre una switchy if...else if...elsees pequeña, que, básicamente, hacer el mismo trabajo. Una diferencia entre ellos que puede marcar la diferencia es que la expresión a probar solo se evalúa de vez en switchcuando, se evalúa para cada uno if. Si es costoso evaluar la expresión, hacerlo una vez es, por supuesto, más rápido que hacerlo cien veces.

La diferencia en la implementación de esos comandos (y todos los scripts en general) difiere bastante entre los navegadores. Es común ver diferencias de rendimiento bastante grandes para el mismo código en diferentes navegadores.

Como difícilmente puede probar el rendimiento de todo el código en todos los navegadores, debe buscar el código que mejor se adapte a lo que está haciendo e intentar reducir la cantidad de trabajo realizado en lugar de optimizar cómo se hace.

Guffa
fuente
7
  1. Si hay una diferencia, nunca será lo suficientemente grande como para ser notada.
  2. N / A
  3. No, todos funcionan de manera idéntica.

Básicamente, use lo que haga que el código sea más legible. Definitivamente, hay lugares donde una u otra construcción hace que sea más limpio, más legible y más fácil de mantener. Esto es mucho más importante que quizás guardar algunos nanosegundos en el código JavaScript.

Jon Benedicto
fuente
55
En javascript especialmente, la semántica y la legibilidad (y, por lo tanto, la mantenibilidad) prevalecen sobre cualquier diferencia de rendimiento localizada if..elsey switchcausada por una combinación única de hardware de computadora y sistema operativo.
jball
2
No sé si estoy de acuerdo, que de hecho puede notar si se utiliza en un bucle con, por ejemplo, una base de datos grande, recorrer un árbol, etc.
ghoppe
2
Definitivamente no estoy de acuerdo. A medida que las aplicaciones web se vuelven cada vez más complejas, esta diferencia podría ser significativa para la aplicación y podría cambiar dependiendo de los navegadores.
joshvermaire
77
Lo importante es escribir código limpio y mantenible. Cuando se ve un problema de rendimiento - perfil. Luego determine qué código corregir. No sacrifique la capacidad de mantenimiento por problemas de rendimiento asumidos.
Jon Benedicto
3
'if else if else ...' es O (n), mientras que 'switch' es O (1) u O (log (n)). ¿Cómo puedes decir honestamente que la diferencia nunca puede ser lo suficientemente grande? Tenga un millón de casos en el interruptor (fácilmente posible si se genera el código) y definitivamente lo notará, por decir lo menos.
Dragonroot
6

Además de la sintaxis, se puede implementar un interruptor utilizando un árbol que lo hace O(log n), mientras que un if / else debe implementarse con un O(n)enfoque de procedimiento. Más a menudo, ambos se procesan procesalmente y la única diferencia es la sintaxis, y además, ¿realmente importa, a menos que esté escribiendo estáticamente 10k casos de if / else de todos modos?

Evan Carroll
fuente
7 años después ... No veo cómo es posible la implementación del árbol, excepto en el caso de valores de casos numéricos constantes).
Ed Staub
4

La respuesta de Pointy sugiere el uso de un objeto literal como alternativa a switcho if/ else. También me gusta este enfoque, pero el código en la respuesta crea un nuevo mapobjeto cada vez dispatchque se llama a la función:

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

Si mapcontiene una gran cantidad de entradas, esto puede generar una sobrecarga significativa. Es mejor configurar el mapa de acción solo una vez y luego usar el mapa ya creado cada vez, por ejemplo:

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
fuente
3

¿Hay una diferencia de rendimiento en Javascript entre una instrucción switch y un if ... else if .... else?

No lo creo, switches útil / breve si quieres prevenir múltiples if-elseafecciones.

¿Es el comportamiento del interruptor y si ... más si ... más es diferente en los navegadores? (Firefox, IE, Chrome, Opera, Safari)

El comportamiento es el mismo en todos los navegadores :)

Sarfraz
fuente
55
switch is useful/short if you want prevent multiple if-else conditions.Sí señor, gran publicación.
NiCk Newman
1
  1. Workbenching puede resultar en algunas diferencias muy pequeñas en algunos casos, pero la forma de procesamiento depende del navegador de todos modos, por lo que no vale la pena molestarse
  2. Debido a diferentes formas de procesamiento
  3. No puede llamarlo un navegador si el comportamiento sería diferente de todos modos
Koen
fuente