134

How can I use a condition inside a switch statement for JavaScript? In the example below, a case should match when the variable liCount is <= 5 and > 0; however, my code does not work:

switch (liCount) {
  case 0:
    setLayoutState("start");
    var api = $("#UploadList").data("jsp");
    api.reinitialise();
    break;
  case liCount <= 5 && liCount > 0:
    setLayoutState("upload1Row");
    var api = $("#UploadList").data("jsp");
    api.reinitialise();
    break;
  case liCount <= 10 && liCount > 5:
    setLayoutState("upload2Rows");
    var api = $("#UploadList").data("jsp");
    api.reinitialise();
    break;
  case liCount > 10:
    var api = $("#UploadList").data("jsp");
    api.reinitialise();
    break;
  default:
    break;
}

Appreciate any advice!

Juan Marco
  • 3,081
  • 2
  • 28
  • 32
haemse
  • 3,971
  • 5
  • 28
  • 40
  • 5
    use if statements instead if u want to do that.. – Naftali Mar 28 '11 at 19:59
  • 4
    You should not ignore everyone telling you to use `if`s, because they are right. This is a terrible application of `switch`. – lincolnk Jul 19 '14 at 00:08
  • I can't believe this solution hasn't been provided. You can do this, the statement just needs to evaluate to the value in the switch clause. So this would work: `var liCount = 2; switch (liCount) { case 0: console.log(0); break; case (liCount<=5 && liCount>0) && liCount: console.log('liCount<=5 && liCount>0'); break; case (liCount<=10 && liCount>5) && liCount: console.log('liCount<=10 && liCount>5'); break; case (liCount>10) && liCount: console.log(liCount); break; }` – Noitidart Dec 24 '16 at 08:56
  • [Duplicatated](https://stackoverflow.com/questions/6665997/switch-statement-for-greater-than-less-than) on Jul 12, 2011 – Mr. Polywhirl Mar 01 '23 at 15:59

14 Answers14

396

This works:

switch (true) {
    case liCount == 0:
        setLayoutState('start');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount<=5 && liCount>0:
        setLayoutState('upload1Row');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount<=10 && liCount>5:
        setLayoutState('upload2Rows');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount>10:
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;                  
}

The only thing necessary is switch(true){...} and for your case expressions to evaluate to booleans.

It works because, the value we give to the switch is used as the basis to compare against. Consequently, the case expressions, also evaluating to booleans will determine which case is run. Could also turn this around, and pass switch(false){..} and have the desired expressions evaluate to false instead of true.. but personally prefer dealing with conditions that evaluate to truthyness. However, it does work too, so worth keeping in mind to understand what it is doing.

Eg: if liCount is 3, the first comparison is true === (liCount == 0), meaning the first case is false. The switch then moves on to the next case true === (liCount<=5 && liCount>0). This expression evaluates to true, meaning this case is run, and terminates at the break. I've added parentheses here to make it clearer, but they are optional, depending on the complexity of your expression.

It's pretty simple, and a neat way (if it fits with what you are trying to do) of handling a long series of conditions, where perhaps a long series of ìf() ... else if() ... else if () ... might introduce a lot of visual noise or fragility.

Use with caution, because it is a non-standard pattern, despite being valid code.

danp
  • 14,876
  • 6
  • 42
  • 48
  • 9
    I think you'd need to have `switch(true) {`, and `case liCount == 0:` right? Otherwise this comparison is `liCount == (liCount <=5 && liCount > 0)`. – loganfsmyth Jan 29 '12 at 18:37
  • Thanks for sharing, I did not know this way of checking nested ifs with switch case. – Anmol Saraf Jan 02 '13 at 11:49
  • Very intriguing and creative solution! – gsklee Apr 26 '13 at 07:28
  • 50
    You know, it's not because you _can_ that you _should_. This is something which needs to be killed with fire. – JBert Jul 18 '14 at 08:03
  • Why complicate yourself with this whereas you could simply use a if() statement, as it's JavaScript job?... – jmpp Oct 24 '14 at 10:20
  • 37
    It's part of the language - consequently, knowing about it is better than not. Clearly, it would not be appropriate for every situation, but on a purely subjective level, I think this is an interesting approach, and more legible/less fragile than a series of ifs/elifs in this case. The important thing to remember is that coding is an expression of intent, coupled with taste and practice. Having more options to clearly express yourself in code is never a bad thing. – danp Oct 26 '14 at 12:01
  • 2
    For me this was very useful and a very nice way to organize my logic where I needed to use a variable name over and over again based on an if condition, but it was an n+1 type scenario so the fact that switch statement case without a break will move onto the next line below was critically useful. – Joseph Astrahan Nov 25 '17 at 03:38
  • 3
    You even opened our eyes to see what the outcome would have been if the switch expression is false like so `switch(false) { `} – bello hargbola Dec 05 '19 at 12:08
  • @JBert if only JavaScript had an equivalent to the "pythonic" way of doing things – Raunaqss Jan 31 '20 at 07:58
31

You've way overcomplicated that. Write it with if statements instead like this:

if(liCount == 0)
    setLayoutState('start');
else if(liCount<=5)
    setLayoutState('upload1Row');
else if(liCount<=10)
    setLayoutState('upload2Rows');

$('#UploadList').data('jsp').reinitialise();

Or, if ChaosPandion is trying to optimize as much as possible:

setLayoutState(liCount == 0 ? 'start' :
               liCount <= 5 ? 'upload1Row' :
               liCount <= 10 ? 'upload2Rows' :
               null);

$('#UploadList').data('jsp').reinitialise();
Community
  • 1
  • 1
Eric
  • 95,302
  • 53
  • 242
  • 374
  • You had to go and one up me. :) – ChaosPandion Mar 28 '11 at 20:06
  • We wrote our posts simultaneously. I didn't see yours until I'd already posted. You appear to be overdoing it now... – Eric Mar 28 '11 at 20:07
  • Wow I didn't really think about the overly complex conditionals. – ChaosPandion Mar 28 '11 at 20:10
  • 1
    @Chaos: yeah, that's probably overdoing it. You'd have to add a null-check to `setLayoutState` as well :P. – Eric Mar 28 '11 at 20:11
  • @Eric - some programmers with more programming laps under their belt than I have say: "just because you can write Javascript without braces (and - in fact with care - semicolons) doesn't mean you should", But I just rewrote some multiple if statements as in your example anyway, so thanks - works fine until there's more than one line to execute after the condition. The ternary solution was a bridge too far for me, though… – Dave Everitt Jun 01 '16 at 14:54
  • `switch-case` has an advantage over this particular solution because it allows the execution of blocks of multiple cases (if no `break` is intentionally omitted in some of them). Here, another `if...else` chain would be needed. Then, `switch-case` has the benefit that after any `break` statement no other condition would be checked. – ellockie Sep 06 '22 at 16:43
9

You want to use if statements:

if (liCount === 0) {
    setLayoutState('start');
} else if (liCount <= 5) {
    setLayoutState('upload1Row');
} else if (liCount <= 10) {
    setLayoutState('upload2Rows');
}
$('#UploadList').data('jsp').reinitialise();  
ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
8

See dmp's answer below. I'd delete this answer if I could, but it was accepted so this is the next best thing :)

You can't. JS Interpreters require you to compare against the switch statement (e.g. there is no "case when" statement). If you really want to do this, you can just make if(){ .. } else if(){ .. } blocks.

Community
  • 1
  • 1
  • 9
    That's incorrect. Here's a demo showing it working: http://jsfiddle.net/Ender/fr3wL/. The ECMAScript standard explicitly states that this is allowed: http://docstore.mik.ua/orelly/webprog/jscript/ch06_05.htm#FOOTNOTE-18 – Ender Mar 28 '11 at 20:13
  • 3
    @Ender How is that the same as what haemse is trying to do? – Aistina Jan 30 '12 at 20:16
  • @Aistina It's not. Since his case conditions produce a true/false value rather than a numerical value, haemse would have needed to test his cases for a truthy value (such as suggested by danp's answer), rather than testing against the numerical value of `liCount`. I was merely pointing out that cwolves original statement that "JS Interpreters require case statements to be static values" was incorrect. cwolves has since revised this statement, so my comment is no longer relevant. – Ender Jan 31 '12 at 17:00
  • Because this doesn't answer the question. He didn't ask for a different way to do it, he asked to make the switch-case work like he wants. "Do it some other way" is almost never a correct answer in spite of us pretty much always thinking it is. We always think we have a better way, but that's not how he wants to do it, making this answer just plain wrong. – Jasmine Jul 21 '14 at 21:19
  • @Jasmine - "You can't, so do it some other way" is perfectly valid, _if it is correct_. My answer is being down-voted because it's just wrong :) As @danp pointed out, you can just switch against `true` and it works. But it's over 3 years old, so I don't really care. –  Jul 21 '14 at 21:24
  • @zyklus So why can't you edit the answer with `true` switch ? B'cos everyone is coming to see the correct answer first. – Sampath May 08 '15 at 11:54
  • @Sampath -- Because that wasn't what I answered ;) People can see dmp's answer which is correct. I'd delete the answer if I could, but it's the accepted answer so I can't. I'll do the next best thing and edit it away :) –  May 08 '15 at 14:34
  • @zyklus Yes,Now it's better.Thanks :) – Sampath May 08 '15 at 20:56
8

You can use fall-through method in switch case.

const x = 'Welcome';

switch (x) {
  case 'Come':
    console.log(1)
    break;

  case 'Welcome':
  case 'Wel':
  case 'come':
    console.log(2)
    break;

  case 'Wel':
    console.log(3)
    break;

  default:
    break;
}

    
> Result => 2
Praveen RL
  • 588
  • 9
  • 13
7
switch (true) {
  case condition0:
    ...
    break;
  case condition1:
    ...
    break;
}

will work in JavaScript as long as your conditions return proper boolean values, but it doesn't have many advantages over else if statements.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • Will It work If I pass some integer say `10` in switch statement? in my case not working not sure what's the reason. – Pardeep Jain Jun 24 '19 at 17:58
  • `10 !== true`, so no. Is there some variable that might have the value `10`? If `x`, then `case x === 10:` would work. – Mike Samuel Jun 26 '19 at 15:20
  • But it should work like other statements for example if you use `if (10) {..}` flow should pass in the `If` condition, isn't it? because 10 or any integer except 0 will be treated as truthy value and allow to enter into the condition. Not sure what's wrong with he switch statement here. – Pardeep Jain Jun 26 '19 at 18:00
  • 1
    @PardeepJain, `switch` simply doesn't work like `if`. `if` tests whether the condition is [truthy](https://tc39.es/ecma262/#sec-toboolean). `switch` tests whether the expression after the `switch` is `===` ([CaseClauseIsSelected step 4](https://tc39.es/ecma262/#sec-runtime-semantics-caseclauseisselected)) to the value of the expression after `case`. – Mike Samuel Jun 26 '19 at 19:50
  • Ohh like that, Thanks. This was totally new to me. @Mike – Pardeep Jain Jun 28 '19 at 05:42
5

if the possible values are integers you can bunch up cases. Otherwise, use ifs.

var api, tem;

switch(liCount){
    case 0:
    tem= 'start';
    break;
    case 1: case 2: case 3: case 4: case 5:
    tem= 'upload1Row';
    break;
    case 6: case 7: case 8: case 9: case 10:
    tem= 'upload2Rows';
    break;
    default:
    break;
}
if(tem) setLayoutState((tem);
api= $('#UploadList').data('jsp');
api.reinitialise();
kennebec
  • 102,654
  • 32
  • 106
  • 127
4

That's a case where you should use if clauses.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
4

If that's what you want to do, it would be better to use if statements. For example:

if(liCount == 0){
    setLayoutState('start');
}
if(liCount<=5 && liCount>0){
    setLayoutState('upload1Row');
}
if(liCount<=10 && liCount>5){
    setLayoutState('upload2Rows');
}             
var api = $('#UploadList').data('jsp');
    api.reinitialise();
Robert Gowland
  • 7,677
  • 6
  • 40
  • 58
Naftali
  • 144,921
  • 39
  • 244
  • 303
2

Your code does not work because it is not doing what you are expecting it to do. Switch blocks take in a value, and compare each case to the given value, looking for equality. Your comparison value is an integer, but most of your case expressions resolve to a boolean value.

So, for example, say liCount = 2. Your first case will not match, because 2 != 0. Your second case, (liCount<=5 && liCount>0) evaluates to true, but 2 != true, so this case will not match either.

For this reason, as many others have said, you should use a series of if...then...else if blocks to do this.

Ender
  • 14,995
  • 8
  • 36
  • 51
1

Notice that we don't pass score to the switch but true. The value we give to the switch is used as the basis to compare against.

The below example shows how we can add conditions in the case: without any if statements.

function getGrade(score) {
    let grade;
    // Write your code here
    switch(true) {
        case score >= 0 && score <= 5:
        grade = 'F';
        break;
        case score > 5 && score <= 10:
        grade = 'E';
        break;
        case score > 10 && score <= 15:
        grade = 'D';
        break;
        case score > 15 && score <= 20:
        grade = 'C';
        break;
        case score > 20 && score <= 25:
        grade = 'B';
        break;
        case score > 25 && score <= 30:
        grade = 'A';
        break;
    }

    return grade;
}
Harshit Pant
  • 1,032
  • 11
  • 14
1

Although in the particular example of the OP's question, switch is not appropriate, there is an example where switch is still appropriate/beneficial, but other evaluation expressions are also required. This can be achieved by using the default clause for the expressions:

switch (foo) {
  case 'bar':
    // do something
    break;
  case 'foo':
    // do something
    break;
  ... // other plain comparison cases
  default:
    if (foo.length > 16) {
      // something specific
    } else if (foo.length < 2) {
      // maybe error
    } else {
      // default action for everything else
    }
}
spikyjt
  • 2,210
  • 21
  • 16
1

If you want pass any value in switch statement and then apply condition on that passing value and evaluate statement then you have to write switch statement under an function and pass parameter in that function and then pass true in switch expression like the below example.

function numberChecker(num){
  let age;
  switch(true){  
      case num >= 0 && num <= 10:
          age = "Child";
      break;
      
      case num >= 10 && num <= 20:
          age = "Teenager";
      break;
      
      case num >= 20 && num <= 30:
          age = "Young";
      break;

      default:
          age = "Undefined!! Enter Age Between 0 - 30";
      break;
      
  }
  
  console.log("WOW You Are " + age);
}
numberChecker(15);
bguiz
  • 27,371
  • 47
  • 154
  • 243
0

(For posterity years later)

It's pretty against convention, but it's also possible to use ternary as a cleaner looking if/else chain, if someone wants to avoid using conditional switch cases.

E.g.

let value;
if (mainCondition) { value = 0; }
else if (subCondition1) { value = 1; }
else if (subCondition2) { value = 2; }
else { value = null; }

Becomes

const value = mainCondition ? 0 :
  subCondition1 ? 1 :
  subCondition2 ? 2 :
  null;

It can quickly become a spaghetti mess if poorly maintained, and most people won't like seeing this or even be able to read it if less experienced, it's non-conventional after all, but it cleans up if else to the point of being nearly as simple as a switch case can be.

Rosseyn
  • 72
  • 2
  • 9