3

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';}
Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157
Gustavo
  • 301
  • 2
  • 5
  • 21
  • If you log `dir` at the top of your function, do you get the expected result? – alex Feb 24 '11 at 01:27
  • 1
    The code is working fine for me in firefox, is there any other code involved? What browser are you using? You also might want to add `var img="";` because it will try to convert both operands to a string when appending, and since you haven't initialized img it just becomes "undefined". :) – Gordon Gustafson Feb 24 '11 at 01:35
  • [`switch...case` uses strict comparison](http://stackoverflow.com/questions/6989902/is-it-safe-to-assume-strict-comparison-in-a-javascript-switch-statement?lq=1); you're comparing a string to an integer. – Blazemonger May 29 '13 at 13:28

7 Answers7

12

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

AlfaTeK
  • 7,487
  • 14
  • 49
  • 90
  • 1
    parseInt is not needed. The `+` unary operator is the way to go: `switch ( +dir ) { ...` – Šime Vidas Feb 24 '11 at 01:48
  • well you were right it seemed that the data fetched is string so just adding the parseInt worked as well as changing the case 1: to case '1': – Gustavo Feb 24 '11 at 01:55
  • 1
    You can convert to int in many different ways, it's just code style :) I prefer to be explicit when doing the conversion rather than using something like +dir that non-javascript programmers (or beginners) could not understand. – AlfaTeK Feb 24 '11 at 01:58
3

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 "===".

Dan Crews
  • 3,067
  • 17
  • 20
2

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

Rob Agar
  • 12,337
  • 5
  • 48
  • 63
2

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.

rsp
  • 107,747
  • 29
  • 201
  • 177
  • 1
    make sure you cast `dir` to an int first. This is a cleaner solution, but still doesn't explain the problem the user is having. :) – Gordon Gustafson Feb 24 '11 at 01:37
  • If the problem is that `dir` is a string then it will work this way. See this fiddle: http://jsfiddle.net/cAg58/ – rsp Feb 24 '11 at 01:43
  • 1. It has to be `+=`, not `=`. 2. You can take out the `.png` suffix to remove the redundancy. Then: `img += arr[dir] + '.png';` – Šime Vidas Feb 24 '11 at 01:46
  • It doesn't have to be += because img is always an empty string to begin with. – rsp Feb 24 '11 at 01:48
0

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

Joe Green
  • 1,745
  • 1
  • 12
  • 17
0

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.

QuinnG
  • 6,346
  • 2
  • 39
  • 47
0

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.

Matt
  • 4,388
  • 1
  • 15
  • 8