Cambiar la declaración de casos múltiples en JavaScript

768

Necesito varios casos en la declaración de cambio en JavaScript, algo así como:

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

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

¿Cómo puedo hacer eso? Si no hay forma de hacer algo así en JavaScript, quiero conocer una solución alternativa que también siga el concepto DRY .

Afshin Mehrabani
fuente
55
Al que votó para cerrar esta pregunta. Tiene más de 5 años y tiene una respuesta aceptada: ¿por qué la votación cerrada?
surfmuggle
@surfmuggle porque no es necesario agregar más respuestas.
Afshin Mehrabani
77
@AfshinMehrabani ¿tal vez pueda protegerse, no cerrarse?
evolutionxbox

Respuestas:

1510

Utilice la función de caída de la switchdeclaración. Se ejecutará un caso coincidente hasta que se encuentre un break(o el final de la switchdeclaración), por lo que podría escribirlo como:

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

   default: 
       alert('Default case');
}
kennytm
fuente
2
De alguna manera me funciona en Chrome, en la consola javascript: switch('10') { case 1, '10': console.log('ok') }imprimeok
nafg
8
@nafg: Intenta switch(1). La etiqueta aquí es solo una expresión de coma.
kennytm
44
@Barney No, sin el descanso puedes pasar al siguiente caso.
Seiyria
1
@Seiyira por definición, no hay un próximo caso después del último. Además, es un defecto.
Barney
101

Esto funciona en JavaScript normal

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

Salud.

Rob Welan
fuente
13
@believesInSanta es literalmente un caso normal con formato extraño (espacios en lugar de líneas nuevas)
Mihail Malostanidis
42

Aquí hay un enfoque diferente que evita la switchdeclaración por completo:

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

cases[ varName ] ? cases[ varName ]() : cases._default();
elclanrs
fuente
55
Definitivamente prefiero esta versión. Fall through es una característica propensa a errores de switch ... case. Es demasiado fácil olvidar una breakdeclaración, y si usas el fallo intencionalmente, esas breakdeclaraciones olvidadas pueden ser muy difíciles de detectar. Esta versión de búsqueda de métodos también tiene muchas características excelentes que switch ... casefaltan, como la extensibilidad dinámica o la capacidad de reemplazar completamente el objeto para lograr el cambio de modo. También es más fácil mantenerse limpiamente organizado, y puede conducir a un código más fácil de mantener. Ver ericleads.com/2012/12/switch-case-considered-harmful
Eric Elliott
31
Siempre agrego un comentario //fallthroughen lugar de breakcada vez que omito intencionalmente el break. Eso ayuda a identificar cuándo es un error y cuándo es intencional.
Mnebuerquo
18
Enfoque intuitivo. Sin embargo, para facilitar la lectura, recomendaría usar la instrucción de cambio nativa.
contactmatt
39
Uno siempre puede rascarse la oreja izquierda pasando su mano derecha por la parte posterior del cuello ... (perdón por mi inglés, quiero decir: "siempre se pueden complicar las cosas tanto como sea posible ... en este caso, evitando la declaración de cambio a favor de esta solución complicada no parece ser lo correcto ...)
Clint Eastwood
25
Estoy realmente sorprendido de cómo esto ha obtenido 34 votos. En términos de legibilidad y mantenibilidad, esto es absolutamente horrible. Si quiero ver qué condiciones desencadenarán algo, una declaración de caso es increíblemente simple y fácil de ver mirando las etiquetas. Por otro lado, su versión requeriría que alguien lea casi todas las líneas y vea qué asignó a dónde. Esto también empeora aún más los casos que desea igualar.
michael
21

En Javascript para asignar múltiples casos en un interruptor, tenemos que definir different case without break inbetweencomo se muestra a continuación:

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

Por favor, vea el ejemplo, haga clic en el enlace

Er. Anurag Jain
fuente
55
Es una técnica común en una plétora de idiomas, no vinculada a JS
drAlberT
13

Si está utilizando ES6, puede hacer esto:

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

O para versiones anteriores de JavaScript, puede hacer esto:

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

Tenga en cuenta que esto no funcionará en navegadores IE más antiguos, pero podría arreglar las cosas con bastante facilidad. Consulte la pregunta para determinar si la cadena está en la lista en JavaScript para obtener más información.

ErikE
fuente
¿Cuál es el beneficio de esto sobre un interruptor?
Bryce Snyder
@BryceSnyder la diferencia entre una expresión y una declaración? ¿Menos tipeo? ¿Menos líneas verticales consumidas? ¿Mayor poder expresivo a través de la concisión y la densidad de representación? ¿Mejor semántica a través de la includespalabra? Elige tu opción.
ErikE
7

En el nodo, parece que puedes hacer esto:

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

Esto hace que el código sea mucho más compacto en algunos casos.

Automatico
fuente
1
Creo que la sintaxis es la misma que en otros entornos JS.
Afshin Mehrabani
1
@AfshinMehrabani Puede ser, solo lo he probado en el contexto de nodejs.
Automatico
Si. ¡Me gusta ahorrar espacio vertical!
Canal
7

Agregando y aclarando la respuesta de Stefano, puede usar expresiones para establecer dinámicamente los valores para las condiciones en el interruptor, por ejemplo:

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

Entonces, en su problema, podría hacer algo como:

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

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

aunque no sea tan SECO ...

Z. Khullah
fuente
aún no se ha probado, pero sería interesante modificarlo varNamedentro de la expresión del caso, espere que varName esté en caché.
Valen
5

puede usar el operador ' in ' ...
depende de la invocación de objeto / hash ...
por lo que es tan rápido como javascript puede 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]()

Disfruta, ZEE

ZEE
fuente
¿Cómo se relaciona esto con el interruptor? puedes aclararlo?
Z. Khullah
¿Por qué quieres hacer que tu código sea "difícil de leer"? Lo primero que me dijeron como programador fue escribir código con la mentalidad de que la siguiente persona que lea su código es un asesino en serie que maneja un hacha y odia no poder entender el código.
MattE
Hola Matt ... Lo presento aquí como una prueba de concepto ... de todos modos, este formulario te proporciona más funcionalidad y flexibilidad ... y solo lo usas si quieres ... o si encuentras una restricción en tu forma habitual de hacer las cosas ... considérelo como una herramienta más en su caja de herramientas del programador ...
ZEE
5

Yo uso así:

switch (true){
     case /Pressure/.test(sensor):{
        console.log('Its pressure!');
        break;
     }
     case /Temperature/.test(sensor):{
        console.log('Its temperature!');
        break;
     }
}
Sergey Volkov
fuente
No necesita usar la gbandera, ya que solo usa las expresiones regulares una vez y las tira a la basura. De hecho, si los mantuviera fuera de la función, la gbandera lo dañaría al intentar hacer coincidir un índice que no sea 0 en .test(s posteriores . También arreglé un error tipográfico donde el caso del interruptor era sensorvariable y no trueconstante para hacer coincidir expresiones booleanas. Ver la edición.
Mihail Malostanidis
Usé este formato para probar contra tipos de archivos. Ej:case /officedocument/.test(type) && /presentation/.test(type): iconClass = "far fa-file-powerpoint red"; break;
tbone849
4

Depende. Switch evalúa una vez y solo una vez. En un partido, todas las declaraciones de casos posteriores hasta "romper" disparan sin importar lo que diga el caso.

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

Me gusta esto por claridad y sintaxis DRY.

varName = "larry";

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

    default: 
       alert('Default case');

}
Kyle Dudley
fuente
2

Puedo ver que hay muchas buenas respuestas aquí, pero ¿qué sucede si necesitamos verificar más de 10 casos? Aquí está mi propio enfoque:

 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
fuente
1
Esto es abuso de la declaración de cambio. Solo if (accessDenied.includes(varName)) return 'Access Denied!'; return 'Access Allowed.'es más que suficiente.
Mihail Malostanidis
2

El problema con los enfoques anteriores es que debe repetir los varios cases cada vez que llama a la función que tiene el switch. Una solución más robusta es tener un mapa o un diccionario .

Aquí un ejemplo

// 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
fuente
1

Puedes hacerlo:

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

o solo una sola línea de código:

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

una pequeña mejora de la respuesta de ErikE

Dedy Abdillah
fuente
1

Para cualquiera que viniera aquí con un problema similar que tuve, que me encontré después de semanas de codificación y agotamiento, mi situación era algo similar a:

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

Siempre el defaultcaso ingresado. Si se encuentra con un problema similar de declaración de cambio de casos múltiples, lo que está buscando es:

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 esto ayude a alguien, me estaba arrancando el pelo antes de recordar usar la caja del interruptor de la misma manera que la uso en mis reductores redux.

Mike K
fuente
0

Una de las posibles soluciones es:

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

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

   default: {
       alert('Default case');
       break;
   }
}
Jackkobec
fuente
Q por favor, ¿qué #ecma es esto?
BG Bruno
Hola. Esto es ES6
Jackkobec
0

Para mí esta es la forma más simple:

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

   default: 
       alert('Default case');
       break;
}
José Pérez Bautista
fuente
-1

Otra forma de hacer múltiples casos en la declaración de cambio, cuando está dentro de una función

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

Morris S
fuente
-2

Podrías escribirlo así:

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

   default: 
       alert('Default case');
       break;
}         
Tim Anishere
fuente
66
Esta es la misma respuesta que todos los demás, arreglaré el "que olvidó, pero piense en eliminar esto.
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
fuente
3
inclusión clásica de jquery :)
ptim
44
No es así como switchse supone que funciona la declaración. Es solo que case "1":no case (num = "1"):.
user4642212
¿Por qué no poner el valor del día dentro de la caja y document.getElementById("result").innerHTML = ....fuera del interruptor y agregar el resultado del valor del día al final?
Steffo Dimfelt
@Xufox Me encanta cómo se sobrescribe literalmente, numpero aún funciona porque switchya se ha evaluado y la asignación produce el valor. Esto es programación por mutación / aprendizaje automático en su máxima expresión.
Mihail Malostanidis
-3

simplemente cambie la condición del interruptor de acercamiento

switch (true) {
    case (function(){ return true; })():
        alert('true');
        break;
    case (function(){ return false; })():
        alert('false');
        break;
    default:
        alert('default');
}
Stefano Favero
fuente
2
Si pone verdadero como expresión de cambio, en la (s) declaración (s) de "caso" puede evaluar lo que quiera siempre que devuelva un valor booleano
Stefano Favero
1
Creo que lo que quiso decir es que puede poner una expresión dentro de la función, que evaluará y devolverá un valor dinámico para el caso, permitiendo así todo tipo de condiciones complejas
Z. Khullah
Para esta nota de @StefanoFavero, en realidad no necesita una función, solo (expression)entre paréntesis, y el valor de retorno debe ser la entrada. Ver mi respuesta
Z. Khullah
¿Por qué te molestaste? Abogo por esta solución porque proporciona flexibilidad para condiciones complejas. Incluso si no le gustan los funcs como condiciones, puede reemplazarlos con múltiples condiciones comoswitch(true) { case (var1 === 0 && var2 === true): {} }
AlexNikonov