Przełącznik JavaScript vs. if… else if… else

143

Chłopaki mam kilka pytań:

  1. Czy istnieje różnica wydajności w JavaScript między switchinstrukcją a instrukcją if...else?
  2. Jeśli tak, dlaczego?
  3. Czy zachowanie switchi jest if...elseróżne w różnych przeglądarkach? (FireFox, IE, Chrome, Opera, Safari)

Powodem zadawania tego pytania jest to, że wydaje mi się, że osiągam lepszą wydajność na switchwyciągu z około 1000 przypadków w przeglądarce Firefox.


Edytowane Niestety to nie jest mój kod, Javascript jest tworzony na serwerze poza skompilowaną biblioteką i nie mam dostępu do kodu. Wywoływana jest metoda, która tworzy skrypt javascript

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

uwaga arrayofvaluesjest listą oddzieloną przecinkami.

to, co produkuje

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

Uwaga: gdzie [name]= nazwa przekazana do funkcji po stronie serwera

Teraz zmieniłem dane wyjściowe funkcji, która ma być wstawiona do TextArea, napisałem kod JavaScript do analizy funkcji i przekonwertowałem go na zestaw caseinstrukcji.

wreszcie uruchamiam tę funkcję i działa dobrze, ale wydajność różni się w IE i Firefox.

John Hartsock
źródło
1
Sugerowałbym próbkę kodu, aby zbadać, co jest optymalne. To znaczy, musi być powód, dla którego o to pytasz, prawda?
jcolebrand
Napisz, co robisz, ponieważ z mojego długiego doświadczenia jest bardzo niewiele przypadków, w których powiedziałbym, że 100-przypadkowa instrukcja przełączania lub 100-częściowa seria, jeśli / else byłaby dobrym pomysłem.
Pointy
przepraszam chłopaki nie setki, ale tysiące warunków
John Hartsock
2
Dziękuję wszystkim za wkład. Ale moim problemem nie była różnica między opcjami if i swith. Był to kod działający w instrukcji. +1 dla was wszystkich za pomoc. Przepraszamy za niedogodności. Czasami wystarczy porozmawiać z inną osobą, aby znaleźć rozwiązanie.
John Hartsock

Odpowiedzi:

113

Odpowiedzi ogólnie:

  1. Tak, zwykle.
  2. Zobacz więcej informacji tutaj
  3. Tak, ponieważ każdy z nich ma inny silnik przetwarzania JS, jednak podczas uruchamiania testu na poniższej stronie przełącznik zawsze wykonywał if, elseif na dużej liczbie iteracji.

Strona testowa

Tommy
źródło
1
Jeśli chcesz uzyskać TLDR, kiedy użyć które warunki warunkowe tutaj, to bezpośredni link do segmentu w artykule, który dotyczy
edhedges
2
@Tommy Dobry artykuł, dzięki za udostępnienie. Jednak artykuł stwierdza, że ​​istnieje pomijalna różnica w wydajności między instrukcjami switchi if/thenw JS. W artykule stwierdzono, że jest to spowodowane nieregularną switchoptymalizacją i różnymi sposobami działania różnych silników JS. Cytat:Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed.
Jasper
3
Czy w opisie przedstawiono coś wymiernego? To brzmi jak wiele domysłów „najlepszych praktyk / przedwczesnej optymalizacji”. Został również napisany 7 lat temu, więc optymalizacje javascript ogromnie się zmieniły w tym czasie. W językach kompilowanych różnica w wydajności między tymi trzema operacjami „prawie nigdy nie jest na tyle znacząca, by się tym przejmować”. Nie przejmuj się optymalizacją rzeczy, które nie wpłyną na rzeczywistą wydajność. Zoptymalizuj czytelność.
Thomson Comer
3
@Tommy « Zobacz więcej informacji tutaj » daje 404, co tam było?
LogicDaemon,
2
@LogicDaemon - IIRC jest linkiem do jakiegoś pola tekstowego oRielly, które wniknęło w kilka dogłębnych rozważań / dyskusji dotyczących wydajności JS
Tommy
61

Czasami lepiej nie używać żadnego. Na przykład w sytuacji „wysyłki” Javascript pozwala robić rzeczy w zupełnie inny sposób:

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

Konfigurowanie rozgałęzień wielotorowych poprzez utworzenie obiektu ma wiele zalet. Możesz dynamicznie dodawać i usuwać funkcje. Możesz utworzyć tabelę wysyłki na podstawie danych. Możesz to sprawdzić programowo. Możesz zbudować programy obsługi z innymi funkcjami.

Istnieje dodatkowy narzut wywołania funkcji, aby uzyskać odpowiednik „przypadku”, ale zaleta (gdy jest wiele przypadków) wyszukiwania skrótu w celu znalezienia funkcji dla określonego klucza.

Spiczasty
źródło
2
Twoja strategia jest dobra i często jej używam. Ale jak wskazał @Michael Geary stackoverflow.com/a/45336805/5936119 , zmienna mapy musi zostać zadeklarowana poza kontekstem wysyłki, w przeciwnym razie zawsze zostanie ponownie obliczona.
Daniel Santana
@DanielSantana to prawda, ale wątpię, czy jest to znacząco drogie. W szczególności, gdy funkcja jest wstępnie przeanalizowana, sam kod nie musi być ponownie generowany, ponieważ tekst jest statyczny.
Pointy
18

Różnica w wydajności między a switchi if...else if...elsejest niewielka, w zasadzie wykonują tę samą pracę. Jedyną różnicą między nimi, która może mieć znaczenie, jest to, że wyrażenie do testowania jest oceniane tylko raz na jakiś switchczas, jest oceniane dla każdego if. Jeśli oszacowanie wyrażenia jest kosztowne, zrobienie tego raz jest oczywiście szybsze niż zrobienie tego sto razy.

Różnica w implementacji tych poleceń (i ogólnie wszystkich skryptów) różni się znacznie między przeglądarkami. Często spotyka się dość duże różnice w wydajności tego samego kodu w różnych przeglądarkach.

Ponieważ trudno jest przetestować wydajność całego kodu we wszystkich przeglądarkach, powinieneś wybrać kod, który najlepiej pasuje do tego, co robisz, i spróbować zmniejszyć ilość wykonywanej pracy, zamiast optymalizować sposób jej wykonywania.

Guffa
źródło
7
  1. Jeśli jest różnica, nigdy nie będzie wystarczająco duża, aby można ją było zauważyć.
  2. Nie dotyczy
  3. Nie, wszystkie działają identycznie.

Zasadniczo używaj tego, co sprawia, że ​​kod jest najbardziej czytelny. Zdecydowanie są miejsca, w których jedna lub druga konstrukcja zapewnia czystszą, czytelniejszą i łatwiejszą w utrzymaniu. Jest to o wiele ważniejsze niż zaoszczędzenie kilku nanosekund w kodzie JavaScript.

Jon Benedicto
źródło
5
Zwłaszcza w javascript semantyka i czytelność (a tym samym łatwość utrzymania) przewyższają wszelkie zlokalizowane różnice w wydajności między if..elsei switchspowodowane przez unikalną kombinację sprzętu komputerowego przeglądarki i systemu operacyjnego.
jball
2
Nie wiem, czy się zgadzam, rzeczywiście można by było zauważyć, jeśli jest używany w pętli z, powiedzmy, dużą bazą danych, przemierzaniem drzewa itp.
ghoppe
2
zdecydowanie się nie zgadzam. Ponieważ aplikacje internetowe stają się coraz bardziej złożone, różnica ta może być znacząca dla aplikacji i może zmieniać się w zależności od przeglądarek.
joshvermaire,
7
Ważną rzeczą jest napisanie czystego, łatwego w utrzymaniu kodu. Kiedy pojawia się problem z wydajnością - profil. Następnie określ, który kod należy naprawić. Nie poświęcaj możliwości konserwacji dla zakładanych problemów z wydajnością.
Jon Benedicto
3
„if else if else…” to O (n), podczas gdy „switch” to O (1) lub O (log (n)). Jak możesz uczciwie stwierdzić, że różnica nigdy nie może być wystarczająco duża? Miej milion przypadków w przełączniku (łatwo to możliwe, jeśli kod zostanie wygenerowany), a na pewno to zauważysz.
dragonroot
6

Inaczej niż składnia, przełącznik można zaimplementować za pomocą drzewa, które go tworzy O(log n), podczas gdy if / else musi zostać zaimplementowane z O(n)podejściem proceduralnym. Częściej oba są przetwarzane proceduralnie, a jedyną różnicą jest składnia, a ponadto czy to naprawdę ma znaczenie - chyba że wpisujesz statycznie 10 tys. Przypadków if / else?

Evan Carroll
źródło
7 lat później ... Nie widzę możliwości implementacji drzewa, z wyjątkiem przypadku stałych liczbowych wartości przypadku).
Ed Staub
4

Odpowiedź Pointy'ego sugeruje użycie dosłownego obiektu jako alternatywy dla switchlub if/ else. To podejście też mi się podoba, ale kod w odpowiedzi tworzy nowy mapobiekt za każdym razem, gdy dispatchfunkcja jest wywoływana:

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

Jeśli mapzawiera dużą liczbę wpisów, może to spowodować znaczne obciążenie. Mapę akcji lepiej ustawić tylko raz, a następnie za każdym razem korzystać z już utworzonej mapy, na przykład:

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
źródło
3

Czy istnieje różnica w działaniu JavaScript między instrukcją switch a instrukcją if ... else if .... else?

Nie sądzę, switchjest przydatne / krótkie, jeśli chcesz zapobiec wielu if-elsewarunkom.

Czy zachowanie przełącznika i if ... else if ... else jest inne w różnych przeglądarkach? (FireFox, IE, Chrome, Opera, Safari)

Zachowanie jest takie samo we wszystkich przeglądarkach :)

Sarfraz
źródło
5
switch is useful/short if you want prevent multiple if-else conditions.Tak proszę pana, świetny post.
NiCk Newman
1
  1. Środowisko pracy może w niektórych przypadkach powodować bardzo małe różnice, ale sposób przetwarzania i tak zależy od przeglądarki, więc nie warto się tym przejmować
  2. Z powodu różnych sposobów przetwarzania
  3. Nie możesz nazwać tego przeglądarką, jeśli zachowanie i tak byłoby inne
Koen
źródło