Commutateur Javascript vs si… sinon si… autre

143

Les gars, j'ai quelques questions:

  1. Existe-t-il une différence de performances en JavaScript entre une switchinstruction et un if...else?
  2. Si oui, pourquoi?
  3. Le comportement switchet le comportement des if...elsenavigateurs sont-ils différents? (FireFox, IE, Chrome, Opera, Safari)

La raison pour laquelle je pose cette question est qu'il semble que j'obtiens de meilleures performances sur une switchdéclaration avec environ 1000 cas dans Firefox.


Edité Malheureusement ce n'est pas mon code, le Javascript est en cours de production depuis une bibliothèque compilée et je n'ai pas accès au code. La méthode qui produit le javascript est appelée

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

note arrayofvaluesest une liste séparée par des virgules.

ce qu'il produit est

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

Remarque: où [name]= le nom passé dans la fonction côté serveur

Maintenant, j'ai changé la sortie de la fonction à insérer dans un TextArea, j'ai écrit du code JavaScript pour analyser la fonction et je l'ai converti en un ensemble d' caseinstructions.

enfin je lance la fonction et elle fonctionne bien mais les performances diffèrent dans IE et Firefox.

John Hartsock
la source
1
Je suggérerais un exemple de code pour examiner ce qui est optimal. Je veux dire, il doit y avoir une raison pour laquelle tu demandes ça, non?
jcolebrand
Veuillez poster ce que vous êtes en train de faire, car il y a très peu de cas dans ma longue expérience pour lesquels je dirais qu'une instruction de commutation de 100 cas ou une série de 100 parties if / else était une bonne idée.
Pointy
désolé les gars pas des centaines mais des milliers de conditions
John Hartsock
2
Tout le monde, merci pour votre contribution. Mais mon problème n'était pas en fait la différence entre les déclarations if et swith. C'était le code qui s'exécutait à l'intérieur de l'instruction. +1 à vous tous pour votre aide. Désolé pour le dérangement. Parfois, il vous suffit de discuter avec une autre personne pour trouver la solution.
John Hartsock

Réponses:

113

Répondre en général:

  1. Oui, généralement.
  2. Voir plus d'informations ici
  3. Oui, car chacun a un moteur de traitement JS différent, cependant, lors de l'exécution d'un test sur le site ci-dessous, le commutateur a toujours effectué le if, elseif sur un grand nombre d'itérations.

Site de test

Tommy
la source
1
Si vous voulez un TLDR indiquant quand utiliser quelles conditions, voici un lien direct vers un segment de l'article traitant de cela: oreilly.com/server-administration/excerpts/even-faster-websites/…
edhedges
2
@Tommy Bon article, merci pour le partage. Cependant, l'article indique qu'il existe une différence de performances négligeable entre les instructions switchet if/thendans JS. L'article indique que cela est dû à une switchoptimisation inégale et aux différentes façons dont les différents moteurs JS fonctionnent. Citation:Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed.
Jasper
3
Y a-t-il quelque chose de quantifiable indiqué dans cette description? Cela ressemble à beaucoup de conjectures de «meilleures pratiques / optimisation prématurée». Il a également été écrit il y a 7 ans, donc les optimisations javascript ont énormément changé à cette époque. Dans les langages compilés, la différence de performances entre ces trois opérations n'est «presque jamais assez importante pour s'en soucier». Ne vous embêtez pas à optimiser les choses qui n'affecteront pas les performances réelles. Optimisez la lisibilité.
Thomson Comer
3
@Tommy « Voir plus d'informations ici » donne 404, qu'y avait-il?
LogicDaemon
2
@LogicDaemon - IIRC est un lien vers une boîte de texte oRielly qui est entrée dans des considérations / discussions approfondies sur les performances JS
Tommy
61

Parfois, il vaut mieux n'utiliser ni l'un ni l'autre. Par exemple, dans une situation de «répartition», Javascript vous permet de faire les choses d'une manière complètement différente:

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 configuration du branchement multi-directionnel en créant un objet présente de nombreux avantages. Vous pouvez ajouter et supprimer des fonctionnalités de manière dynamique. Vous pouvez créer la table d'expédition à partir des données. Vous pouvez l'examiner par programme. Vous pouvez créer les gestionnaires avec d'autres fonctions.

Il y a la surcharge supplémentaire d'un appel de fonction pour obtenir l'équivalent d'un "cas", mais l'avantage (quand il y a beaucoup de cas) d'une recherche de hachage pour trouver la fonction pour une touche particulière.

Pointu
la source
2
Votre stratégie est bonne et je l'utilise souvent. Mais comme indiqué par @Michael Geary stackoverflow.com/a/45336805/5936119 , la variable de carte doit être déclarée en dehors du contexte de répartition, sinon elle sera toujours réévaluée.
Daniel Santana
@DanielSantana c'est vrai mais je doute que ce soit beaucoup plus cher. En particulier, une fois qu'une fonction est initialement analysée, le code lui-même n'a pas besoin d'être régénéré, car le texte est statique.
Pointy
18

La différence de performance entre a switchet if...else if...elseest faible, ils font essentiellement le même travail. Une différence entre eux qui peut faire une différence est que l'expression à tester n'est évaluée qu'une fois de temps en switchtemps, elle est évaluée pour chacun if. S'il est coûteux d'évaluer l'expression, le faire une fois est bien sûr plus rapide que de le faire cent fois.

La différence d'implémentation de ces commandes (et de tous les scripts en général) diffère un peu entre les navigateurs. Il est courant de voir des différences de performances assez importantes pour le même code dans différents navigateurs.

Comme vous pouvez difficilement tester les performances de tout le code dans tous les navigateurs, vous devez choisir le code qui correspond le mieux à ce que vous faites et essayer de réduire la quantité de travail effectuée plutôt que d'optimiser la façon dont cela est fait.

Guffa
la source
7
  1. S'il y a une différence, elle ne sera jamais assez grande pour être remarquée.
  2. N / A
  3. Non, ils fonctionnent tous de la même manière.

En gros, utilisez ce qui rend le code le plus lisible. Il y a certainement des endroits où l'une ou l'autre des constructions est plus propre, plus lisible et plus maintenable. C'est bien plus important que d'économiser peut-être quelques nanosecondes en code JavaScript.

Jon Benedicto
la source
5
En javascript en particulier, la sémantique et la lisibilité (et donc la maintenabilité) l'emportent sur toute différence de performance localisée entre if..elseet switchcausée par une combinaison unique de matériel informatique et de système d'exploitation.
jball
2
Je ne sais pas si je suis d'accord, cela pourrait en effet être remarqué s'il est utilisé dans une boucle avec, disons, une grande base de données, traversant un arbre etc.
ghoppe
2
je ne suis absolument pas d'accord. à mesure que les applications Web deviennent de plus en plus complexes, cette différence pourrait être significative pour l'application et pourrait changer en fonction des navigateurs.
joshvermaire
7
L'important est d'écrire un code propre et maintenable. Lorsqu'un problème de performances est détecté - profil. Déterminez ensuite le code à corriger. Ne sacrifiez pas la maintenabilité pour des problèmes de performances supposés.
Jon Benedicto
3
'if else if else ...' est O (n), tandis que 'switch' est soit O (1) ou O (log (n)). Comment pouvez-vous honnêtement affirmer que la différence ne peut jamais être assez grande? Ayez un million de cas en switch (facilement possible si le code est généré) et vous le remarquerez certainement pour le moins.
Dragonroot
6

Autre que la syntaxe, un commutateur peut être implémenté en utilisant un arbre qui le fait O(log n), tandis qu'un if / else doit être implémenté avec une O(n)approche procédurale. Le plus souvent, ils sont tous deux traités de manière procédurale et la seule différence est la syntaxe, et de plus, est-ce vraiment important - à moins que vous ne tapiez statiquement 10k cas de if / else de toute façon?

Evan Carroll
la source
7 ans plus tard ... Je ne vois pas comment l'implémentation de l'arbre est possible, sauf dans le cas des valeurs numériques constantes).
Ed Staub
4

La réponse de Pointy suggère l'utilisation d'un objet littéral comme alternative à switchou if/ else. J'aime aussi cette approche, mais le code de la réponse crée un nouvel mapobjet à chaque fois que la dispatchfonction est appelée:

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 mapcontient un grand nombre d'entrées, cela peut créer une surcharge importante. Il est préférable de ne configurer la carte d'action qu'une seule fois, puis d'utiliser la carte déjà créée à chaque fois, par exemple:

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
la source
3

Y a-t-il une différence de préformance en Javascript entre une instruction switch et une if ... else if .... else?

Je ne pense pas, switchc'est utile / court si vous voulez éviter plusieurs if-elseconditions.

Le comportement de switch et if ... else if ... else est-il différent d'un navigateur à l'autre? (FireFox, IE, Chrome, Opera, Safari)

Le comportement est le même dans tous les navigateurs :)

Sarfraz
la source
5
switch is useful/short if you want prevent multiple if-else conditions.Oui monsieur, super message.
NiCk Newman
1
  1. Workbenching peut entraîner de très petites différences dans certains cas, mais le mode de traitement dépend de toute façon du navigateur, donc cela ne vaut pas la peine d'être dérangé
  2. En raison de différentes méthodes de traitement
  3. Vous ne pouvez pas appeler cela un navigateur si le comportement serait différent de toute façon
Koen
la source