Gustavo
Gustavo

Reputation: 311

trouble with SWITCH javascript always executing default case

well i have this trouble and ive been dealing with but i just cant get it to work

i have this function

function getDirections(dir)
{
var img;
switch(dir)
    {
    case 0:
    img+='N.png';
    break;  
    case 1:
    img+='NE.png';
    break;
    case 2:
    img+='E.png';
    break;
    case 3:
    img+='SE.png';
    break;
    case 4:
    img+='S.png';
    break;
    case 5:
    img+='SO.png';
    break;
    case 6: 
    img+='O.png';
    break;
    case 7:
    img+='NO.png';
    break;
    default:
    alert('enetered default but direction='+dir);
    }
return img;
}

quite simple right? now i have this interval set to 5000 ms to call getDirections(variable), the function works well the first time its called but after that , it always enter in the default clause and it also alerts the 'entered default but direction=dirvalue' , i mean even if dir is a value between 0-7 it will always enter to default: but it would alert the value so it was supossed to enter to one of the cases.

i made the same using else if and it worked so i dont know what its wrong with SWITCH

if(dir==0){img+='N.png';}
else if(dir==1){img+='NE.png';}
else if(dir==2){img+='E.png';}
else if(dir==3){img+='SE.png';}
else if(dir==4){img+='S.png';}
else if(dir==5){img+='SO.png';}
else if(dir==6){img+='O.png';}
else if(dir==7){img+='NO.png';}

Upvotes: 3

Views: 14273

Answers (7)

Dan Crews
Dan Crews

Reputation: 3607

I know I'm a bit late to the party, but I thought it might be important for anyone who doesn't understand why the "ifs" worked and the switch didn't. It's likely no one will read this answer, but I found it while searching for something else, so perhaps someone will find this helpful anyway:

Your switch is this:

function getDirections(dir) {
    var img;
    switch(dir) {
        case 0:
            img+='N.png';
            break;  
        case 1:
            img+='NE.png';
            break;
        case 2:
            img+='E.png';
            break;
        case 3:
            img+='SE.png';
            break;
        case 4:
            img+='S.png';
            break;
        case 5:
            img+='SO.png';
            break;
        case 6: 
            img+='O.png';
            break;
        case 7:
            img+='NO.png';
            break;
        default:
            alert('enetered default but direction='+dir);
    }
    return img;
}

This is not the same as a series of double equals (==) but a series of triple equals (===). It would be equivalent to:

if (dir === 0) {
    img+='N.png';
} else if (dir === 1) {
    img+='NE.png';
} else if (dir === 2) {
    img+='E.png';
} else if (dir === 3) {
    img+='SE.png';
} else if (dir === 4) {
    img+='S.png';
} else if (dir === 5) {
    img+='SO.png';
} else if (dir === 6) {
    img+='O.png';
} else if (dir === 7) {
    img+='NO.png';
} else {
    alert('enetered default but direction='+dir);
}

In the world of "==", the integer 2 IS the same as the string "2", but not in the land of "===".

Upvotes: 3

rsp
rsp

Reputation: 111374

Using an array instead of a chain of if/else blocks or a giant switch statement will be faster, more flexible and less error-prone. Also, you wouldn't have to worry if dir is a number or a string. Instead of:

if(dir==0){img+='N.png';}
else if(dir==1){img+='NE.png';}
else if(dir==2){img+='E.png';}
else if(dir==3){img+='SE.png';}
else if(dir==4){img+='S.png';}
else if(dir==5){img+='SO.png';}
else if(dir==6){img+='O.png';}
else if(dir==7){img+='NO.png';}

you can store the file names in an array:

var images = [
    'N.png', 'NE.png', 'E.png', 'SE.png', 'S.png', 'SO.png', 'O.png', 'NO.png'
];

or arguably more readable:

var images = "N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');

and then use just:

img = images[dir];

Full implementation of getDirections using an array would be:

var images = "N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');
function getDirections(dir) {
    var img = images[dir];
    if (!img) {
        alert("something");
    }
    return img;
}

Does it work for you?

If images is used only in that one function then you may want to store it as a property of the function to avoid your namespace pollution like this:

function getDirections(dir) {
    var img = getDirections.images[dir];
    if (!img) {
        alert("something");
    }
    return img;
}
getDirections.images =
    "N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');

or use a closure.

Upvotes: 2

Matt
Matt

Reputation: 4388

I pasted your code into an HTML file and ran it with the following buttons:

<button onclick="alert(getDirections(2))">Switch / Int</button>
<button onclick="alert(getDirections('2'))">Switch / String</button>
<button onclick="alert(getDirections2(2))">If-Else / Int</button>
<button onclick="alert(getDirections2('2'))">If-Else / String</button>

When calling the switch-version with a plain 2, it works as expected. Calling it with '2' makes it drop through to the default line. The if-else version works as expected in both cases. So the issue is probably that switch doesn't do an implicit conversion and == does.

Upvotes: 0

QuinnG
QuinnG

Reputation: 6424

I just ran the code in FireFox/FireBug and called the function this way

getDirections(0);
getDirections('1');
getDirections("2");

The first one does it correctly and the next two enter default. They are strings and not integer which is what the cases are looking for. I added

case "2":
img+='NO2.png';
break;

and then only the middle one entered the default. Obviously there is an issue with the way you are calling the function. It is likely passing a string. I also used your if-else block (added an else{alert(dir);} and that returned the correct value for each call.

Javascript can do on the fly conversion (I think there's a better word for that) between strings and ints (and others). This is occuring when you do the comparrison using ==. If you change the comparison in the ifs to === you get the same behavior as with the switch block.

Upvotes: 0

Rob Agar
Rob Agar

Reputation: 12459

I'd guess that for some reason dir is being passed in as a string. Try changing case 1: to case '1':

Upvotes: 2

AlfaTeK
AlfaTeK

Reputation: 7765

That is weird... try to make sure that dir is an int, do this before the switch:

dir = parseInt(dir);

If the alert shows the value correctly it should enter the switch, but still it can "look" correct but be of a different data type. Do the conversion manually to ensure it's an int

Upvotes: 12

Joe Green
Joe Green

Reputation: 1777

Hard to explain why, but the default: case also need a break; statement after it like all the other cases.

Upvotes: 0

Related Questions