Alternar instrução vários casos em JavaScript


768

Preciso de vários casos na instrução switch em JavaScript, algo como:

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

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

Como eu posso fazer isso? Se não há como fazer algo assim em JavaScript, quero conhecer uma solução alternativa que também siga o conceito DRY .


5
Para quem votou para encerrar esta questão. Ele tem mais de 5 anos e tem uma resposta aceita - por que a votação apertada?
Surfmuggle

@ surfmuggle porque não é necessário adicionar mais respostas.
Afshin Mehrabani

7
@AfshinMehrabani talvez possa ser protegido, não fechado?
Evoluçãoxbox

Respostas:


1510

Use o recurso de detalhamento da switchdeclaração. Um caso correspondente será executado até que um break(ou o final da switchinstrução) seja encontrado, para que você possa escrever como:

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

   default: 
       alert('Default case');
}


2
De alguma forma, ele trabalha para mim no Chrome, no console javascript: switch('10') { case 1, '10': console.log('ok') }impressõesok
nafg

8
@nafg: Tente switch(1). O rótulo aqui é apenas uma expressão de vírgula.
Kennytm # /

4
@ Barney Não, sem o intervalo você pode passar para o próximo caso.
Seiyria

1
@Seiyira, por definição, não existe um próximo caso após o último. Além disso, é um padrão.
Barney

101

Isso funciona em JavaScript regular

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

Felicidades.


13
@believesInSanta é fallthrough caso literalmente apenas normal com formatação estranha (espaços em vez de novas linhas)
Mihail Malostanidis

42

Aqui está uma abordagem diferente, evitando a switchdeclaração completamente:

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

cases[ varName ] ? cases[ varName ]() : cases._default();

5
Eu definitivamente prefiro esta versão. Fall through é um recurso propenso a erros do switch ... case. É muito fácil esquecer uma breakdeclaração e, se você usar o intencionalmente, essas breakdeclarações esquecidas podem ser muito difíceis de identificar. Essa versão de pesquisa de método também possui muitos recursos excelentes switch ... case, como extensibilidade dinâmica ou a capacidade de substituir completamente o objeto para realizar a alternância de modo. Também é mais fácil manter-se organizado de maneira limpa e pode levar a um código mais sustentável. Veja ericleads.com/2012/12/switch-case-considered-harmful
Eric Elliott

31
Eu sempre adiciono um comentário //fallthroughno lugar de breaksempre que eu omitir intencionalmente break. Isso ajuda a identificar quando é um erro e quando é intencional.
Mnebuerquo

18
Abordagem intuitiva. No entanto, para facilitar a leitura, recomendo usar a instrução switch nativa.
contactmatt

39
Pode-se sempre arranhar a orelha esquerda passando a mão direita pela nuca ... (desculpe pelo meu inglês, quero dizer: "sempre é possível complicar as coisas o máximo possível ... neste caso, evitando a declaração do interruptor a favor desta solução complicada não parece ser a coisa certa a fazer ...)
Clint Eastwood

25
Estou realmente impressionado com o resultado. Em termos de legibilidade e manutenção, isso é absolutamente horrível. Se eu quiser ver quais condições acionarão algo, uma declaração de caso é incrivelmente simples e fácil de ver, observando os rótulos. Por outro lado, sua versão exigiria que alguém lesse praticamente todas as linhas e veja o que você atribuiu onde. Isso também fica ainda pior quanto mais casos você deseja corresponder.
7286 Michael

21

No Javascript, para atribuir vários casos em um comutador, temos que definir os different case without break inbetweendados abaixo:

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

Veja o exemplo, clique no link


5
É uma técnica comum em uma pletora de idiomas, não vinculada ao JS
drAlberT 12/12/13

13

Se você estiver usando o ES6, poderá fazer o seguinte:

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

Ou para versões anteriores do JavaScript, você pode fazer isso:

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

Observe que isso não funcionará em navegadores IE mais antigos, mas você pode consertar as coisas com bastante facilidade. Consulte a pergunta para determinar se a string está na lista em javascript para obter mais informações.


Qual é o benefício disso em relação a um switch?
Bryce Snyder

@BryceSnyder a diferença entre uma expressão e uma declaração? Menos digitação? Menos linhas verticais consumidas? Maior poder expressivo através da sucessão e densidade de representação? Melhor semântica através da includespalavra? Faça sua escolha.
18719 ErikE

7

No nó, parece que você tem permissão para fazer isso:

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

Isso torna o código muito mais compacto em alguns casos.


1
Eu acho que a sintaxe é a mesma que outros ambientes JS.
Afshin Mehrabani

1
@AfshinMehrabani Pode ser que eu apenas o testei no contexto do nodejs.
Automatico

Sim. Eu gosto de economizar espaço vertical!
Canal

7

Adicionando e esclarecendo a resposta de Stefano, você pode usar expressões para definir dinamicamente os valores para as condições no switch, por exemplo:

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

Portanto, no seu problema, você pode fazer algo como:

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

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

embora não seja tão SECO ..


ainda não testado, mas seria interessante modificar varNamedentro da expressão de caso, espere que varName seja armazenado em cache.
Valen

5

você pode usar o operador ' in ' ...
depende da invocação de objeto / hash ...
então é o mais rápido que o javascript pode ser ...

// 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]()

Aproveite, ZEE


como isso se relaciona com a troca? você pode esclarecer isso?
Z. Khullah

por que você gostaria de tornar seu código "difícil de ler". A primeira coisa que me disseram como programador foi escrever código com a mentalidade de que a próxima pessoa que lê o código é um machado com serial killer e ele odeia não ser capaz de entender o código.
Matte

Oi Matt ... Estou apresentando aqui como uma prova de conceito ... de qualquer forma, este formulário fornece mais funcionalidade e flexibilidade ... e você só o usa se quiser ... ou se encontrar uma restrição em seu forma usual de fazer as coisas ... considerar ir como mais uma ferramenta em sua caixa de ferramentas programador ...
ZEE

5

Eu uso assim:

switch (true){
     case /Pressure/.test(sensor):{
        console.log('Its pressure!');
        break;
     }
     case /Temperature/.test(sensor):{
        console.log('Its temperature!');
        break;
     }
}

Você não precisa usar a gbandeira, pois só usa as expressões regulares uma vez e as joga fora. De fato, se você os mantivesse fora da função, o gsinalizador o prejudicaria ao tentar corresponder a partir de um índice diferente de 0 nos .test(s subsequentes . Também corrigi um erro de digitação em que o caso do comutador estava na sensorvariável e não trueconstante para corresponder expressões booleanas. Veja a edição.
Mihail Malostanidis 03/02/19

Eu usei esse formato para testar contra tipos de arquivos. Ex:case /officedocument/.test(type) && /presentation/.test(type): iconClass = "far fa-file-powerpoint red"; break;
tbone849 20/02

4

Depende. O switch avalia uma vez e apenas uma vez. Em uma partida, todas as declarações de caso subsequentes até o 'break' disparam, não importa o que o caso diga.

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>


3

Eu gosto disso por clareza e sintaxe DRY.

varName = "larry";

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

    default: 
       alert('Default case');

}

2

Percebo que há muitas boas respostas aqui, mas o que acontece se precisarmos verificar mais de 10 casos? Aqui está minha própria abordagem:

 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'));

1
Isso é abuso da instrução switch. Apenas if (accessDenied.includes(varName)) return 'Access Denied!'; return 'Access Allowed.'é mais que suficiente.
Mihail Malostanidis 02/02/19

2

O problema com as abordagens acima é que você deve repetir os vários cases toda vez que chamar a função que possui o switch. Uma solução mais robusta é ter um mapa ou um dicionário .

Aqui um exemplo

// 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')
}


1

Você consegue fazer isso:

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

ou apenas uma única linha de código:

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

um pouco de melhoria da resposta de ErikE


1

Para quem vem aqui com um problema semelhante que já tive, depois de semanas de codificação e exaustão, minha situação era algo parecido com:

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

Sempre o defaultcaso inserido. Se você estiver enfrentando um problema semelhante de instrução de comutador de vários casos, o que procura é:

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

Espero que isso ajude alguém, eu estava arrancando meu cabelo antes de lembrar de usar a caixa do interruptor da mesma maneira que em meus redutores de redux.


0

Uma das soluções possíveis é:

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

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

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

Q pls qual #ecma é esse?
BG Bruno

Olá. Este é o ES6 #
30742 Jackkobec

0

Para mim, esta é a maneira mais simples:

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

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

-1

Outra maneira de executar vários casos na instrução switch, quando dentro de uma função

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


-2

Você poderia escrever assim:

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

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

6
Esta é a mesma resposta que todos os outros, vou corrigir o "que você esqueceu, mas pense em excluir isso.
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>

3
inclusão jquery clássico :)
ptim 08/07/16

4
Não é assim que a switchdeclaração deve funcionar. É só que case "1":não case (num = "1"):.
user4642212

Por que não colocar o valor do dia dentro da caixa e document.getElementById("result").innerHTML = ....fora da chave e adicionar o resultado do valor do dia no final?
Steffo Dimfelt 22/08/1918

@Xufox Eu amo como ele literalmente substitui, nummas ainda funciona porque o switchjá foi avaliado e a atribuição gera o valor. Isso é programação por mutação / aprendizado de máquina no seu melhor.
Mihail Malostanidis 02/02/19

-3

basta mudar a condição da chave

switch (true) {
    case (function(){ return true; })():
        alert('true');
        break;
    case (function(){ return false; })():
        alert('false');
        break;
    default:
        alert('default');
}

2
Se você colocar verdadeira como a expressão switch, no "caso" Statement (s) você pode avaliar o que quiser desde que você retornar um boolean
Stefano Favero

1
Eu acho que ele quis dizer é que você pode colocar uma expressão dentro da função, que irá avaliar e retornar um valor dinâmico para o caso, permitindo assim que todos os tipos de condições complexas
Z. Khullah

Para esta nota do @StefanoFavero, você realmente não precisa de uma função, apenas (expression)entre parênteses, e o valor de retorno deve ser a entrada. Veja minha resposta
Z. Khullah

por que você usou isso ?? Defendo esta solução porque fornece uma flexibilidade para condições complexas. Mesmo se você não gosta funcs como condições, você pode substituí-los com você várias condições, tais comoswitch(true) { case (var1 === 0 && var2 === true): {} }
AlexNikonov
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.