Переключить оператор несколько случаев в JavaScript


768

Мне нужно несколько случаев в выражении switch в JavaScript, что-то вроде:

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

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

Как я могу это сделать? Если в JavaScript нет способа сделать что-то подобное, я хочу узнать альтернативное решение, которое также следует концепции DRY .


5
Тому, кто проголосовал, чтобы закрыть этот вопрос. Ему более 5 лет, и он уже получил ответ - зачем закрытое голосование?
surfmuggle

@surfmuggle, потому что нет необходимости добавлять больше ответов.
Афшин Мехрабани

7
@AfshinMehrabani может быть это можно защитить, а не закрыть?
evolutionxbox

Ответы:


1511

Используйте функцию провала в switchзаявлении. Соответствующий регистр будет выполняться до тех пор, пока не будет найден break(или конец switchоператора), так что вы можете написать его так:

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

   default: 
       alert('Default case');
}


2
Каким-то образом это работает для меня в Chrome, в консоли javascript: switch('10') { case 1, '10': console.log('ok') }printsok
nafg

8
@nafg: попробуй switch(1). Метка здесь - просто выражение запятой.
Кеннитм

4
@ Барни Нет, без перерыва вы можете перейти к следующему делу.
Сейрия

1
@Seiyira по определению, нет следующего дела после последнего. Кроме того, это по умолчанию.
Барни

101

Это работает в обычном 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);

Приветствия.


13
@believesInSanta - это буквально обычный случай падения со странным форматированием (пробелы вместо перевода строки)
Михаил Малостанидис

42

Вот другой подход, избегающий switchутверждения в целом:

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

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

5
Я определенно предпочитаю эту версию. Падение - склонная к ошибкам особенность switch ... case. Слишком легко забыть breakутверждение, и если вы намеренно используете провал, эти забытые breakутверждения будет очень трудно обнаружить. Эта версия поиска метода также обладает множеством switch ... caseнедостатков, таких как динамическая расширяемость или возможность полной замены объекта для переключения режимов. Это также легче поддерживать в чистоте, и может привести к большему количеству поддерживаемого кода. См. Ericleads.com/2012/12/switch-case-considered-harmful
Эрик Эллиотт

31
Я всегда добавляю комментарий //fallthroughвместо того, breakкогда я намеренно опускаю break. Это помогает определить, когда это ошибка и когда она преднамеренная.
Mnebuerquo

18
Интуитивный подход. Однако для удобства чтения я бы порекомендовал использовать собственный оператор switch.
contactmatt

39
Всегда можно поцарапать левое ухо, пропуская его правую руку через заднюю часть шеи ... (извините за мой английский, я имею в виду: "всегда можно максимально усложнить вещи ... в этом случае, избегая оператора switch в пользу этого сложного решения, кажется, не то, что нужно делать ...)
Клинт Иствуд

25
Я действительно поражен тем, как это набрало 34 голоса. С точки зрения читабельности и ремонтопригодности, это абсолютно ужасно. Если я хочу посмотреть, какие условия будут вызывать что-либо, то заявление о кейсе невероятно просто и легко увидеть, посмотрев на ярлыки. С другой стороны, ваша версия потребует, чтобы кто-то читал почти каждую строку и видел, что вы назначили. Это также становится еще хуже, чем больше дел вы хотите сопоставить.
Майкл

21

В Javascript, чтобы назначить несколько случаев в переключателе, мы должны определить, different case without break inbetweenкак указано ниже:

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

Пожалуйста, посмотрите пример нажмите на ссылку


5
Это обычная техника в множестве языков, не связанных с JS
drAlberT

13

Если вы используете ES6, вы можете сделать это:

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

Или для более ранних версий JavaScript вы можете сделать это:

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

Обратите внимание, что это не сработает в старых браузерах IE, но вы можете довольно легко это исправить. См. Вопрос определения, находится ли строка в списке в javascript для получения дополнительной информации.


В чем преимущество этого по сравнению с выключателем?
Брайс Снайдер

@BryceSnyder разница между выражением и утверждением? Меньше печатать? Меньше вертикальных линий потребляется? Большая выразительная сила через краткость и плотность представления? Лучше семантика через includesслово? Выбирайте.
ErikE

7

В узле кажется, что вы можете сделать это:

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

В некоторых случаях это делает код более компактным.


1
Я думаю, что синтаксис такой же, как в других средах JS.
Афшин Мехрабани

1
@AfshinMehrabani Возможно, я проверял это только в контексте nodejs.
Automatico

Да. Мне нравится экономить вертикальное пространство!
Канал

7

Добавляя и уточняя ответ Стефано, вы можете использовать выражения, чтобы динамически устанавливать значения для условий в switch, например:

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

Так что в вашей проблеме вы можете сделать что-то вроде:

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

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

хотя не так много СУХОГО ..


еще не проверено, но было бы интересно изменить varNameвнутри выражения case, ожидайте, что varName кэшируется вами.
Вален

5

Вы можете использовать оператор ' in ' ...
полагается на вызов объекта / хеша ...
так что это так быстро, как может быть javascript ...

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

Наслаждайся, ZEE


как это связано с переключением? Вы можете это уточнить?
З. Хулла,

почему вы хотите сделать ваш код "трудным для чтения". Первое, что мне сказали как программисту, было написать код с мыслью, что следующий человек, читающий ваш код, - серийный убийца, владеющий топором, и он ненавидит неспособность понять код.
MattE

Привет, Мэтт ... Я представляю это здесь как доказательство концепции ... в любом случае, эта форма предоставляет вам больше функциональности и гибкости ... и вы используете ее только, если хотите ... или если вы найдете ограничение в вашем обычная форма действий ... рассмотрите их как еще один инструмент в вашем наборе инструментов программиста ...
ZEE

5

Я использую так:

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

Вам не нужно использовать gфлаг, так как вы используете регулярные выражения только один раз и выбрасываете их. На самом деле, если вы держите их вне функции, gфлаг будет вредить вам, пытаясь сопоставить его с индексом, отличным от 0, для последующих .test(s. Я также исправил опечатку, в которой регистр переключателя был sensorпеременным, а не trueпостоянным для сопоставления логических выражений. Смотрите редактирование.
Михаил Малостанидис

Я использовал этот формат для проверки типов файлов. Пример:case /officedocument/.test(type) && /presentation/.test(type): iconClass = "far fa-file-powerpoint red"; break;
tbone849

4

Это зависит. Свитч оценивает один раз и только один раз. После матча все последующие утверждения кейса до «перерыва» срабатывают независимо от того, что говорится в кейсе.

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

Мне нравится это для ясности и сухого синтаксиса.

varName = "larry";

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

    default: 
       alert('Default case');

}

2

Я вижу, что здесь есть много хороших ответов, но что произойдет, если нам нужно проверить более 10 случаев? Вот мой собственный подход:

 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
Это злоупотребление заявлением о смене. Просто if (accessDenied.includes(varName)) return 'Access Denied!'; return 'Access Allowed.'более чем достаточно.
Михаил Малостанидис

2

Проблема с вышеуказанными подходами состоит в том, что вам приходится повторять несколько caseсекунд каждый раз, когда вы вызываете функцию, которая имеет switch. Более надежное решение - иметь карту или словарь .

Вот пример

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

Ты можешь сделать это:

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

или просто одна строка кода:

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

небольшое улучшение от ответа ErikE


1

Для любого, кто приезжал сюда с похожей проблемой, с которой я столкнулся, с которой я столкнулся после нескольких недель кодирования и выгорания, моя ситуация была чем-то похожим на:

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

Всегда defaultдело вводится. Если вы сталкиваетесь с похожей проблемой оператора переключения нескольких случаев, вам нужно:

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

Надеюсь, это кому-нибудь поможет, я выдернул волосы, прежде чем не забыть использовать корпус переключателя так же, как я использую его в своих редукторных редукторах.


0

Одним из возможных решений является:

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

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

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

Q Просьба #ecma это?
БГ Бруно

Всем привет. Это ES6
Jackkobec


-1

Другой способ сделать несколько случаев в операторе switch, когда внутри функции

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


-2

Вы можете написать это так:

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

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

6
Это тот же ответ, что и у всех остальных, я исправлю «то, что вы забыли, но подумайте об удалении этого»
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
классическое включение jquery :)
ptim

4
Это не то, как switchутверждение должно работать. Просто case "1":нет case (num = "1"):.
user4642212

Почему бы не поместить дневное значение в регистр и document.getElementById("result").innerHTML = ....вне коммутатора и добавить результат дневного значения в конце?
Стеффо Димфельт

@Xufox Мне нравится, как он буквально перезаписывает, numно он все еще работает, потому что switchон уже был оценен, и присвоение дает значение. Это программирование с помощью мутации / машинного обучения во всей красе.
Михаил Малостанидис

-3

просто переключите состояние переключателя

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

2
Если в выражении-переключателе вы
Stefano

1
Я думаю, что он имел в виду, что вы можете поместить в функцию выражение, которое будет оценивать и возвращать динамическое значение для кейса, тем самым допуская всевозможные сложные условия
Z. Khullah

Для этого примечания @StefanoFavero вам на самом деле не нужна функция, только (expression)в скобках, а возвращаемое значение должно быть входным. Смотрите мой ответ
З. Хулла

почему ты это использовал? Я защищаю это решение, потому что оно обеспечивает гибкость для сложных условий. Даже если вам не нравятся функи как условия, вы можете заменить их несколькими условиями, такими какswitch(true) { case (var1 === 0 && var2 === true): {} }
AlexNikonov
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.