Переключення оператора кількох випадків у JavaScript


766

Мені потрібно кілька випадків в операторі переключення в JavaScript, щось на зразок:

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

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

Як я можу це зробити? Якщо в JavaScript немає можливості зробити щось подібне, я хочу знати альтернативне рішення, яке також відповідає концепції DRY .


5
Для того, хто проголосував за закриття цього питання. Їй більше 5 років і є прихильна відповідь - навіщо закривати голосування?
surfmuggle

@surfmuggle, оскільки не потрібно додавати більше відповідей.
Афшин Мехрабані

7
@AfshinMehrabani, можливо, це можна захистити, а не закрити?
evolutionxbox

Відповіді:


1506

Скористайтеся функцією 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') }printok
nafg

8
@nafg: Спробуйте switch(1). Мітка тут - лише вираз із комою.
kennytm

4
@Barney Ні, без перерви ви можете перейти до наступного випадку.
Сейрія

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
Інтуїтивний підхід. Однак для читабельності я рекомендую скористатися нативним оператором перемикача.
contactmatt

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

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

Додаючи та уточнюючи відповідь Стефано, ви можете використовувати вирази для динамічного встановлення значень для умов перемикача, наприклад:

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вираз регістру, очікуйте, що 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

Мені це подобається для наочності та синтаксису DRY.

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

2

Проблема вищезазначених підходів полягає в тому, що вам потрібно повторювати кілька cases кожного разу, коли ви викликаєте функцію, яка має 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')

трохи покращення від відповіді Еріке


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 pls що # ecma це?
БГ Бруно

Привіт там. Це ES6
Jackkobec


-1

Інший спосіб робити кілька випадків у операторі перемикання, коли знаходиться у функції

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
Це та сама відповідь, як і всі інші, я виправлю "що ви забули, але подумайте про те, щоб видалити це.
Гонт

-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 = ....поза комутатором і не додати результат денного значення в кінці?
Steffo Dimfelt

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

-3

просто переключіть стан перемикача приблизно

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

2
Якщо ви ставите true як вираз перемикача, у викладенні "case" ви можете оцінити все, що хочете, за умови повернення булевого
тексту

1
Я думаю, що він мав на увазі те, що ви можете помістити вираз всередині функції, яка оцінить і поверне динамічне значення для випадку, дозволяючи таким чином всілякі складні умови
З. Хулла

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

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