Przełącz instrukcję wielu przypadków w JavaScript

765

Potrzebuję wielu przypadków w instrukcji switch w JavaScript, coś w stylu:

switch (varName)
{
   case "afshin", "saeed", "larry": 
       alert('Hey');
       break;

   default: 
       alert('Default case');
       break;
}

Jak mogę to zrobić? Jeśli nie ma sposobu, aby zrobić coś takiego w JavaScript, chcę poznać alternatywne rozwiązanie, które również opiera się na koncepcji DRY .

Afshin Mehrabani
źródło
5
Do tego, który głosował za zamknięciem tego pytania. Ma ponad 5 lat i ma potwierdzoną odpowiedź - po co głosować blisko?
surfmuggle
@ surfmuggle, ponieważ nie trzeba dodawać więcej odpowiedzi.
Afshin Mehrabani
7
@AfshinMehrabani może to może być chronione, a nie zamknięte?
evolutionxbox

Odpowiedzi:

1505

Skorzystaj z funkcji zastępczej switchinstrukcji. Dopasowana sprawa będzie działać do momentu znalezienia break(lub końca switchinstrukcji), dzięki czemu można ją zapisać w następujący sposób:

switch (varName)
{
   case "afshin":
   case "saeed":
   case "larry": 
       alert('Hey');
       break;

   default: 
       alert('Default case');
}
kennytm
źródło
2
Jakoś to działa dla mnie w Chrome, w konsoli javascript: switch('10') { case 1, '10': console.log('ok') }printok
nafg
8
@nafg: Spróbuj switch(1). Etykieta tutaj to tylko przecinek.
kennytm
4
@Barney Nie, bez przerwy możesz przejść do następnej sprawy.
Seiyria
1
@Seiyira z definicji, nie ma następnego przypadku po ostatnim. Poza tym jest to ustawienie domyślne.
Barney,
101

Działa to w zwykłym JavaScript

function theTest(val) {
  var answer = "";
  switch( val ) {
    case 1: case 2: case 3:
      answer = "Low";
      break;
    case 4: case 5: case 6:
      answer = "Mid";
      break;
    case 7: case 8: case 9:
      answer = "High";
      break;
    default:
      answer = "Massive or Tiny?";
  } 
  return answer;  
}

theTest(9);

Twoje zdrowie.

Rob Welan
źródło
13
@believesInSanta to dosłownie zwykły przypadek przewrotny z dziwnym formatowaniem (spacje zamiast nowych linii)
Mihail Malostanidis
42

Oto inne podejście, switchcałkowicie unikające stwierdzenia:

var cases = {
  afshin: function() { alert('hey'); },
  _default: function() { alert('default'); }
};
cases.larry = cases.saeed = cases.afshin;

cases[ varName ] ? cases[ varName ]() : cases._default();
elclanrs
źródło
5
Zdecydowanie wolę tę wersję. Fall Fall to podatna na błędy funkcja switch ... case. Zbyt łatwo jest zapomnieć o breakoświadczeniu, a jeśli użyjesz upadku celowo, te zapomniane breakoświadczenia mogą być bardzo trudne do wykrycia. Ta wersja metody wyszukiwania ma również wiele wspaniałych funkcji, których switch ... casebrakuje, takich jak dynamiczna rozszerzalność lub możliwość całkowitego zastąpienia obiektu w celu osiągnięcia przełączenia trybu. Łatwiej jest też utrzymać porządek i może prowadzić do łatwiejszego do utrzymania kodu. Zobacz ericleads.com/2012/12/switch-case-consanted-harmful
Eric Elliott
31
Zawsze dodam komentarz //fallthroughzamiast tego, breakgdy celowo pomijam break. Pomaga to zidentyfikować, kiedy jest to błąd, a kiedy celowo.
Mnebuerquo
18
Intuicyjne podejście. Jednak ze względu na czytelność polecam użycie natywnej instrukcji switch.
contactmatt
39
Zawsze można podrapać lewe ucho, przesuwając prawą rękę przez kark ... (przepraszam za mój angielski, mam na myśli: „zawsze można skomplikować wszystko tak bardzo, jak to możliwe ... w tym przypadku, unikając instrukcji switch na korzyść tego skomplikowanego rozwiązania nie wydaje się właściwe ...)
Clint Eastwood,
25
Naprawdę jestem zdumiony, jak uzyskało 34 głosy. Pod względem czytelności i łatwości konserwacji jest to absolutnie przerażające. Jeśli chcę zobaczyć, jakie warunki coś spowodują, stwierdzenie przypadku jest niezwykle proste i łatwe do zobaczenia, patrząc na etykiety. Z drugiej strony, twoja wersja wymagałaby, aby ktoś przeczytał prawie każdą linię i sprawdził, co przypisałeś. Sytuacja staje się jeszcze gorsza, im więcej przypadków chcesz dopasować.
Michael
21

W Javascript, aby przypisać wiele spraw do przełącznika, musimy zdefiniować different case without break inbetweenjak podano poniżej:

   <script>
      function checkHere(varName){
        switch (varName)
           {
           case "saeed":
           case "larry":
           case "afshin":
                alert('Hey');
                break;
          case "ss":
               alert('ss');
               break;
         default:
               alert('Default case');
               break;
       }
      }
     </script>

Zobacz przykład kliknij link

Er. Anurag Jain
źródło
5
Jest to powszechna technika w wielu językach, niezwiązanych z JS
drAlberT
13

Jeśli używasz ES6, możesz to zrobić:

if (['afshin', 'saeed', 'larry'].includes(varName)) {
   alert('Hey');
} else {
   alert('Default case');
}

Lub we wcześniejszych wersjach JavaScript możesz to zrobić:

if (['afshin', 'saeed', 'larry'].indexOf(varName) !== -1) {
   alert('Hey');
} else {
   alert('Default case');
}

Pamiętaj, że to nie będzie działać w starszych przeglądarkach IE, ale możesz dość łatwo załatać sprawę. Zobacz pytanie, czy ciąg znaków znajduje się na liście w javascript, aby uzyskać więcej informacji.

ErikE
źródło
Jaka jest z tego korzyść w porównaniu z przełącznikiem?
Bryce Snyder
@BryceSnyder różnica między wyrażeniem a wyrażeniem? Mniej pisania? Zużyto mniej linii pionowych? Większa moc ekspresji dzięki zwięzłości i gęstości reprezentacji? Lepsza semantyka poprzez includessłowo? Wybierz swój.
ErikE
7

W węźle wydaje się, że możesz to zrobić:

data = "10";
switch(data){
case "1": case "2": case "3": //put multiple cases on the same line to save vertical space.
   console.log("small"); break;
case "10": case "11": case "12":
   console.log("large"); break;
default:
   console.log("strange");
   break;
}

To sprawia, że ​​w niektórych przypadkach jest znacznie bardziej zwarty kod.

Automatico
źródło
1
Myślę, że składnia jest taka sama jak w innych środowiskach JS.
Afshin Mehrabani
1
@AfshinMehrabani Być może przetestowałem to tylko w kontekście nodejs.
Automatico
Tak. Lubię oszczędzać miejsce w pionie!
Channel
7

Dodając i wyjaśniając odpowiedź Stefano, możesz użyć wyrażeń, aby dynamicznie ustawić wartości warunków w przełączniku, np .:

var i = 3
switch (i) {
    case ((i>=0 && i<=5)?i:-1): console.log('0-5'); break;
    case 6: console.log('6');
}

Więc w swoim problemie możesz zrobić coś takiego:

var varName = "afshin"
switch (varName) {
    case (["afshin", "saeed", "larry"].indexOf(varName)+1 && varName):
      console.log("hey");
      break;

    default:
      console.log('Default case');
}

chociaż nie jest tak SUCHO ...

Z. Khullah
źródło
jeszcze nie przetestowane, ale byłoby interesujące zmodyfikować varNamewyrażenie wyrażenia, spodziewaj się, że zmienna nazwa jest buforowana.
Valen
5

możesz użyć operatora „ in ” ...
polega na wywołaniu obiektu / skrótu ...
tak szybko, jak javascript może być ...

// assuming you have defined functions f(), g(a) and h(a,b) 
// somewhere in your code
// you can define them inside the object but... 
// the code becomes hard to read, I prefer this way

o = { f1:f, f2:g, f3:h };

// if you use "STATIC" code can do:
o['f3']( p1, p2 )

// if your code is someway "DYNAMIC", to prevent false invocations
// m brings the function/method to be invoked (f1, f2, f3)
// and you can rely on arguments[] to solve any parameter problems
if ( m in o ) o[m]()

Ciesz się, ZEE

ZEE
źródło
jak to się ma do zamiany? możesz to wyjaśnić?
Z. Khullah,
dlaczego chcesz, aby Twój kod był „trudny do odczytania”. Pierwszą rzeczą, którą powiedziano mi jako programistom, było pisanie kodu w myśleniu, że następna osoba czytająca twój kod jest seryjnym zabójcą z toporem i nie cierpi, że nie rozumie kodu.
MattE
Cześć Matt ... Przedstawiam go tutaj jako dowód koncepcji ... w każdym razie ten formularz zapewnia większą funkcjonalność i elastyczność ... i używasz go tylko, jeśli chcesz ... lub jeśli znajdziesz ograniczenie w swoim zwykła forma robienia rzeczy ... traktuj ir jako kolejne narzędzie w przyborniku programisty ...
ZEE
5

Używam w ten sposób:

switch (true){
     case /Pressure/.test(sensor):{
        console.log('Its pressure!');
        break;
     }
     case /Temperature/.test(sensor):{
        console.log('Its temperature!');
        break;
     }
}
Siergiej Wołkow
źródło
Nie musisz używać gflagi, ponieważ używasz wyrażeń regularnych tylko raz i wyrzucasz je. W rzeczywistości, jeśli trzymasz je poza funkcją, gflaga zaszkodzi ci, próbując dopasować z indeksu różnego od 0 na kolejnych .test(s. Naprawiłem także literówkę, w której wielkość liter przełączania była sensorzmienna, a nie truestała, w celu dopasowania wyrażeń boolowskich. Zobacz edycję.
Mihail Malostanidis
Użyłem tego formatu do testowania typów plików. Np .:case /officedocument/.test(type) && /presentation/.test(type): iconClass = "far fa-file-powerpoint red"; break;
tbone849
4

To zależy. Switch ocenia raz i tylko raz. Podczas meczu wszystkie kolejne stwierdzenia sprawy aż do „przerwania” ognia, bez względu na to, co mówi sprawa.

var onlyMen = true;
var onlyWomen = false;
var onlyAdults = false;
 
 (function(){
   switch (true){
     case onlyMen:
       console.log ('onlymen');
     case onlyWomen:
       console.log ('onlyWomen');
     case onlyAdults:
       console.log ('onlyAdults');
       break;
     default:
       console.log('default');
   }
})(); // returns onlymen onlywomen onlyadults
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>

Ronnie Royston
źródło
3

Podoba mi się to ze względu na przejrzystość i składnię DRY.

varName = "larry";

switch (true)
{
    case ["afshin", "saeed", "larry"].includes(varName) :
       alert('Hey');
       break;

    default: 
       alert('Default case');

}
Kyle Dudley
źródło
2

Widzę, że jest tu wiele dobrych odpowiedzi, ale co się stanie, jeśli będziemy musieli sprawdzić więcej niż 10 przypadków? Oto moje własne podejście:

 function isAccessible(varName){
     let accessDenied = ['Liam','Noah','William','James','Logan','Benjamin',
                        'Mason','Elijah','Oliver','Jacob','Daniel','Lucas'];
      switch (varName) {
         case (accessDenied.includes(varName)?varName:null): 
             return 'Access Denied!';
         default:
           return 'Access Allowed.';
       }
    }

    console.log(isAccessible('Liam'));
Aravinda Meewalaarachchi
źródło
1
Jest to nadużycie instrukcji switch. Po prostu if (accessDenied.includes(varName)) return 'Access Denied!'; return 'Access Allowed.'to więcej niż wystarczające.
Mihail Malostanidis
2

Problem z powyższymi podejściami polega na tym, że musisz powtarzać kilka cases za każdym razem, gdy wywołujesz funkcję, która ma switch. Bardziej niezawodnym rozwiązaniem jest posiadanie mapy lub słownika .

Oto przykład

// the Map, divided by concepts
var dictionary = {
  timePeriod: {
    'month': [1, 'monthly', 'mensal', 'mês'],
    'twoMonths': [2, 'two months', '2 motnhs', 'bimestral', 'bimestre'],
    'trimester': [3, 'trimesterly', 'quarterly', 'trimestral'],
    'semester': [4, 'semesterly', 'semestral', 'halfyearly'],
    'year': [5, 'yearly', 'anual', 'ano']
  },
  distance: {
    'km': [1, 'kms', 'kilometre', 'kilometers', 'kilometres'],
    'mile': [2, 'mi', 'miles'],
    'nordicMile': [3, 'nordic mile', 'mil(10km)', 'scandinavian mile']
  },
  fuelAmount: {
    'ltr': [1, 'l', 'litre', 'Litre', 'liter', 'Liter'],
    'gal(imp)': [2, 'imp gallon', 'imperial gal', 'gal(UK)'],
    'gal(US)': [3, 'US gallon', 'US gal'],
    'kWh': [4, 'KWH']
  }
};

//this function maps every input to a certain defined value
function mapUnit (concept, value) {
  for (var key in dictionary[concept]) {
    if (key === value || 
      dictionary[concept][key].indexOf(value) !== -1) {
      return key
    }
  }
  throw Error('Uknown "'+value+'" for "'+concept+'"')
}

//you would use it simply like this
mapUnit("fuelAmount", "ltr") // => ltr
mapUnit("fuelAmount", "US gal") // => gal(US)
mapUnit("fuelAmount", 3) // => gal(US)
mapUnit("distance", "kilometre") // => km
  
//now you can use the switch statement safely without the need 
//to repeat the combinations every time you call the switch
var foo = 'monthly'
switch (mapUnit ('timePeriod', foo)) {
  case 'month': 
    console.log('month')
    break
  case 'twoMonths': 
    console.log('twoMonths')
    break
  case 'trimester': 
    console.log('trimester')
    break
  case 'semester': 
    console.log('semester')
    break
  case 'year': 
    console.log('year')
    break
  default:
    throw Error('error')
}

João Pimentel Ferreira
źródło
1

Możesz to zrobić:

alert([
  "afshin", 
  "saeed", 
  "larry",
  "sasha",
  "boby",
  "jhon",
  "anna",
  // ...
].includes(varName)? 'Hey' : 'Default case')

lub tylko jeden wiersz kodu:

alert(["afshin", "saeed", "larry",...].includes(varName)? 'Hey' : 'Default case')

mała poprawa w stosunku do odpowiedzi ErikE

Dedy Abdillah
źródło
1

Dla każdego, kto tu przyjeżdża z podobnym problemem, z którym miałem do czynienia po tygodniach kodowania i wypalenia zawodowego, moja sytuacja była podobna do:

switch (text) {
  case SOME_CONSTANT || ANOTHER_CONSTANT:
    console.log('Case 1 entered');

  break;

  case THIRD_CONSTANT || FINAL_CONSTANT:
    console.log('Case 2 entered');

  break;

  default:
    console.log('Default entered');
}

Zawsze defaultwpisana sprawa. Jeśli napotykasz podobny problem z instrukcją przełączania wielu spraw, to czego szukasz:

switch (text) {
  case SOME_CONSTANT:
  case ANOTHER_CONSTANT:
    console.log('Case 1 entered');

  break;

  case THIRD_CONSTANT:
  case FINAL_CONSTANT:
    console.log('Case 2 entered');

  break;

  default:
    console.log('Default entered');
}

Mam nadzieję, że to komuś pomoże, odciągnąłem włosy, zanim przypomniałem sobie, aby używać skrzynki przełączników w taki sam sposób, jak używam jej w moich reduktorach redux.

Mike K.
źródło
0

Jednym z możliwych rozwiązań jest:

const names = {
afshin: 'afshin',
saeed: 'saeed',
larry: 'larry'
};

switch (varName) {
   case names[varName]: {
       alert('Hey');
       break;
   }

   default: {
       alert('Default case');
       break;
   }
}
Jackkobec
źródło
Pytanie, który to # ecma?
BG Bruno
Cześć. To jest ES6
Jackkobec
0

Dla mnie jest to najprostszy sposób:

switch (["afshin","saeed","larry"].includes(varName) ? 1 : 2) {
   case 1: 
       alert('Hey');
       break;

   default: 
       alert('Default case');
       break;
}
José Pérez Bautista
źródło
-1

Innym sposobem wykonywania wielu przypadków w instrukcji switch, gdy są one wewnątrz funkcji

function name(varName){
  switch (varName) {
     case 'afshin':
     case 'saeed':
     case 'larry':
       return 'Hey';
     default:
       return 'Default case';
   }
}
        
console.log(name('afshin')); //Hey

Morris S.
źródło
-2

Możesz to napisać w ten sposób:

switch (varName)
{
   case "afshin": 
   case "saeed": 
   case "larry": 
       alert('Hey');
       break;

   default: 
       alert('Default case');
       break;
}         
Tim Anishere
źródło
6
To jest ta sama odpowiedź, jak wszyscy inni, naprawię „zapomniane”, ale pomyśl o usunięciu tego.
Gaunt
-3
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Example1</title>
    <link rel="stylesheet" href="css/style.css" >
    <script src="js/jquery-1.11.3.min.js" type="text/javascript"></script>
    <script>
        function display_case(){
            var num =   document.getElementById('number').value;

                switch(num){

                    case (num = "1"):
                    document.getElementById("result").innerHTML = "You select day Sunday";
                    break;

                    case (num = "2"):
                    document.getElementById("result").innerHTML = "You select day  Monday";
                    break;

                    case (num = "3"):
                    document.getElementById("result").innerHTML = "You select day  Tuesday";
                    break;

                    case (num = "4"):
                    document.getElementById("result").innerHTML = "You select day  Wednesday";
                    break;

                    case (num = "5"):
                    document.getElementById("result").innerHTML = "You select day  Thusday";
                    break;

                    case (num = "6"):
                    document.getElementById("result").innerHTML = "You select day  Friday";
                    break;

                    case (num = "7"):
                    document.getElementById("result").innerHTML = "You select day  Saturday";
                    break;

                    default:
                    document.getElementById("result").innerHTML = "You select day  Invalid Weekday";
                    break
                }

        }
    </script>
</head>
<body>
    <center>
        <div id="error"></div>
        <center>
            <h2> Switch Case Example </h2>
            <p>Enter a Number Between 1 to 7</p>
            <input type="text" id="number" />
            <button onclick="display_case();">Check</button><br />
            <div id="result"><b></b></div>
        </center>
    </center>
</body>
Kirandeep Singh
źródło
3
włączenie klasycznej jquery :)
ptim
4
To nie tak switchpowinno działać oświadczenie. Po prostu case "1":nie case (num = "1"):.
user4642212
Dlaczego nie umieścić wartości dziennej w obudowie i document.getElementById("result").innerHTML = ....poza przełącznikiem i dodać wynik wartości dziennej na końcu?
Steffo Dimfelt
@Xufox Uwielbiam to, jak dosłownie nadpisuje, numale nadal działa, ponieważ switchzostało już ocenione i przypisanie daje wartość. Jest to programowanie przez mutację / uczenie maszynowe w najlepszym wydaniu.
Mihail Malostanidis
-3

wystarczy zmienić podejście do przełącznika

switch (true) {
    case (function(){ return true; })():
        alert('true');
        break;
    case (function(){ return false; })():
        alert('false');
        break;
    default:
        alert('default');
}
Stefano Favero
źródło
2
Jeśli podasz wartość true jako wyrażenie przełączające, w instrukcji „case” możesz ocenić, co chcesz, pod warunkiem, że zwrócisz wartość logiczną
Stefano Favero
1
Myślę, że miał na myśli to, że można wstawić wyrażenie do funkcji, która oceni i zwróci wartość dynamiczną dla sprawy, umożliwiając w ten sposób wszelkiego rodzaju złożone warunki
Z. Khullah,
Do tej notatki @StefanoFavero tak naprawdę nie potrzebujesz funkcji, tylko (expression)w nawiasie, a zwracana wartość musi być danymi wejściowymi. Zobacz moją odpowiedź
Z. Khullah,
dlaczego to wykorzystałeś? Opowiadam się za tym rozwiązaniem, ponieważ zapewnia ono elastyczność w złożonych warunkach. Nawet jeśli nie lubisz grzybów jako warunków, możesz je zastąpić wieloma warunkami, takimi jakswitch(true) { case (var1 === 0 && var2 === true): {} }
AlexNikonov