trouble with SWITCH javascript always executing default case - javascript

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

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

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

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

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.

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

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.

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.

Related

Switch case break and undefined value in JS

I'm creating a little game in HTML/JS/CSS for an exercise, and I've created a board game of 100 squares with <tr></tr and <td></td>.
There are two players on my board and, on each round, I check the squares around the two players, to see if there is a weapon or a player on this square.
But to check if there is a player on the square, I need to check if the square exist first. That' why I use a lot of switch case statements:
switch (true) {
case (squareAround != undefined): //I check if a square around is not undefined
switch (true) { //if the square exists, let's check if there is a player on it
case (playerOnIt === true):
//start the fight if there is a player on it
}
}
This is of course a simplified version. The break and default statements are not here.
The problem is, sometimes the square is "undefined" and the program doesn't go further, just as I want. But some other times, the square is detected as "undefined" but the program continues anyways. The case is clearly "false" but the switch case isn't working.
I used the console, and this exemple where it doesn't work : in the two first cases the square exist, and then it shows me the two HTML element.
But in the third cases, it's false, but the switch case works anyway, goes further, and gives me the HTML element... which is "undefined" !
What can possibly go wrong ?
Thanks for the help
Edit : here is some original code, ton answer the question of someone. But I don't know if it can help :
switch (true) {
case ($('td')[numberCasePlayer + i + l] != undefined):
switch (true) {
case ($('td')[numberCasePlayer + i + l].getAttribute('playeronit') === playeronitCheck):
fight()
break
}
case ($('td')[numberCasePlayer + i + m] != undefined):
switch (true) {
case ($('td')[numberCasePlayer + i + m].getAttribute('playeronit') === playeronitCheck):
fight()
break
}
case ($('td')[numberCasePlayer + i + n] != undefined):
switch (true) {
case ($('td')[numberCasePlayer + i + n].getAttribute('playeronit') === playeronitCheck):
fight()
break
}
case ($('td')[numberCasePlayer + i].getAttribute('weapon') === 'true'):
$('#' + $('td')[numberCasePlayer + i].getAttribute('weapontype')).css('display', 'none')
}
break
The right format for the switch statement is like:
switch(someVariable) {
case value1: doSomething; break;
case value2: doSomething; break;
case value3: doSomething; break;
...
default: doSomething;
}
It's straight forward if you do it with just if statements.
if(squareAround) {
if(playerOnIt) {
//start the fight if there is a player on it
}
}

How does that switch case work in JS? What does mean switch(true)?

I am currently working on project, where are parts of code that I don't understand. One of them you can see below (written in JS):
switch (true) {
case parseInt(data):
return 'data';
case parseInt(row):
return 'row';
default:
return 'default';
}
I created JSFiddle to test this switch(true) statement and to see how it behaves. It always returns 'default' string. Can someone explain to me what is happening there, please?
JSFiddle switch test
A switch in JavaScript simply compares if the value of the case is strictly equal (===) to what’s inside the switch (in this case true). This is usually used to compare strings, but booleans would also work, although it is less common. Take the following example:
switch (true) {
case 1 + 1 === 3:
return 'A';
case 2 * 2 === 4:
return 'B';
default:
return 'C';
}
This code would return 'B' as it is the first case to match true. If none of the cases would match true, it would return 'C'.
Regarding your specific scenario; I would recommend rewriting your code to the following:
if (parseInt(data) === true) {
return 'data';
}
if (parseInt(row) === true) {
return 'row';
}
return 'default';
This code does the exact same thing as yours, but it is immediately clear to the reader what is happening.
I am not sure what your goal is with this function, so I cannot recommend the best way to solve your problem. Although, I can explain to you why it might not be working.
The parseInt function will always return a number or NaN (in case the input cannot be parsed). Although a number can be truthy, it will never be strictly true. That's why your function always returns 'default'. Again, I don't know what your goal is, but you might want to check if the value is truthy instead of true:
if (parseInt(data)) {
// Data can be parsed to a number and is not 0
return 'data';
}
if (parseInt(row)) {
// Row can be parsed to a number and is not 0
return 'row';
}
return 'default';
It'll execute the first case that evaluates to true. If no case is true, it'll execute the default block
For example:
switch (true) {
case 1 === 1:
console.log('ok1');
break;
case 2 === 2:
console.log('ok2');
break;
default:
console.log('not ok');
}
will console.log('ok1')

JavaScript: right switch-case statement

My code is such:
switch(typeof src) {
case 'string':
case 'boolean':
return String(src).toLowerCase().indexOf(value.toLowerCase()) > -1;
case 'object':
return true;
default:
return false;
}
but code checker say that: n unconditional "break" statement shall terminate every non-empty switch-clause
will it be right and normal if I will write it so?
switch(typeof src) {
case 'string':
case 'boolean':
return String(src).toLowerCase().indexOf(value.toLowerCase()) > -1;
break;
case 'object':
return true;
break;
default:
return false;
// in default i need it or not?
}
or I missed somewhat else?
Your code checker is wrong then, because a return terminates the entire function in which the switch statement resides.
Anything after a return (like the break it wants you to put there) will be unreachable and never executed.
Whether or not this is beautiful or good practise is debatable, but I would say it is OK.
If you do not have a return statement or anything else that terminates the current block or jumps out of it (like continue inside a loop), then you usually want to put a break and the end of each case block to prevent fallthrough, but there are actually cases where you want fallthrough.
So your code checker is more of an opinion checker really.
No, break statement is not necessary if you return from a default case.
You must add break statement for all your cases which you want to operate and stop switch's work, otherwise default is operated returning from function.
Switch Pattern from "JavaScript Patterns" by Stoyan Stefanov.
var inspect_me = 0,
result = '';
switch (inspect_me) {
case 0:
result = "zero";
break;
case 1:
result = "one";
break;
default:
result = "unknown";
}

How To Use JavaScript Switch Case in Filed Validation

I am trying a simple input validation at This Demo and as you can see I am using some nested if statements (which can be more for applying more validation rules). Now my question is if you can help me to use JavaScript Switch Statement instead of theses if statement
the reason which I got confused is the (expression) and default: part of the statement which I am totally confused how to use them in my case?
switch(expression) {
case n:
code block
break;
case n:
code block
break;
default:
default code block
}
and here is my code:
$(function () {
$("#pro").on("click", function (e) {
inputData = $.trim($('input[type="text"]').val());
if (inputData == ""){
alert("Field Can not be Empty");
}
else if (inputData.length<3){
alert("Field Can Be Less Than 4");
}
else
{
alert($('input[type="text"]').val());
}
e.preventDefault();
});
});
Thanks
That's not the way, how switch statement works. You can not write different expressions in the case of a switch. It can only compare the expression to a single value defined in a case statement.
See another explanation at: Expression inside switch case statement
An example of how to use switch() statement would be like this:
var expression = "1";
switch(expression) {
case "1":
//this will be executed
break;
case "2":
//wont be executed
break;
default:
//wont be executed, since a match was found
}
It is better to use one switch instead of using 2-3 if/then/else statements.
You can find more examples here: http://www.w3schools.com/js/js_switch.asp
Although not a good way to use switches you ca proceed like this:
switch(true){
case (inputData == "") :
// your code
break;
case (inputData.length<3) :
//your code
break;
default:
//your code
break;
}
If else statement is suit here. It is difficult to use switch here.
Let us look the switch
$(function () {
$("#pro").on("click", function (e) {
inputData = $.trim($('input[type="text"]').val());
var len = inputData.length;
switch(len)
{
case 0:
alert("Field Can not be Empty");
break;
case 1:
alert("Field Can't Be Less Than 4");
break;
case 2:
alert("Field Can't Be Less Than 4");
break;
case 3:
alert("Field Can't Be Less Than 4");
break;
default:
alert($('input[type="text"]').val());
}
e.preventDefault();
});
});
The code looks lengthy and become make problem for more condition. So the if else is the better solution here.
switch demo
You can write expressions in case clauses but you have to return the value for comparison.
$(function () {
var $input = $('input[type="text"]');
$('button').on('click', validateInput)
function validateInput(e) {
e.preventDefault();
var alertMsg = "";
var inputData = $.trim($input.val());
switch(inputData) {
case "":
alertMsg = "Field Can not be Empty";
break;
case (inputData.length < 4 && inputData):
alertMsg = "Field Can't Be Less Than 4";
break;
default:
alertMsg = inputData;
}
alert(alertMsg);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text"><button>Click here</button>
In my case I used switch as an exercise to a form in Bootstrap. Due so I let the break between the cases as the program keeps tracking for more fields, so it doesn't need to check every variant on it and jumps to the next field. I made and object with the conditions that the switch should look for. Pls, do remember that this is a schoolar exercise and my boundaries were quite clear: no if/else allowed. Here is the code
//taking input value field
let mailLine = inputEmail.value;
//obj mail
let mailObj = {
case1 : (mailLine == ""),
case2 : (!checkValidity(mailLine)),
//function check, no need to place it here!
}
//if the cases are true
switch (true) {
case mailObj.case1:
inputEmail.classList.add("is-invalid");//bootstrap div
document.getElementById("errorEmail").textContent = "No empty field allowed";
counter ++; //for more stuff in the code
break; //left it on purpose. No itineration. So it goes to password, city...
case mailObj.case2:
inputEmail.classList.add("is-invalid");
document.getElementById("errorEmail").textContent = "Not right mail format";
counter ++;
break;
default:
inputEmail.classList.remove("is-invalid");
inputEmail.classList.add("is-valid");
document.getElementById("okEmail").textContent = "Right mail format";
break;
}

Switch combining cases string regex and number

Is there a way to create multiple cases in a single Javascript switch statement?
In my code I receive the value of a field via jQuery.
Is it possible that one case checks for string regex and another for number of the same variable?
I am thinking along the lines of:
var field = $(this).val();
var msg;
switch (field)
{
case field.test('Yes'):
msg = "FOO\n";
break;
case 10:
msg = "BAR\n";
break;
}
Although I saw here: Switch statement for string matching in JavaScript
That the way to use switch on strings is by sending the switch statement a "true" value.
What would be the most concise (and correct!) way to achieve this?
OK, compiling both answers above my code that worked and was most elegant IMO is:
var fieldVal = $(this).val();
var msg;
switch (true)
{
case /Yes/.test(fieldVal):
msg = "FOO";
break;
case fieldVal > 10 :
msg = "BAR";
break;
}
this works as separate if statements since we are evaluating whether or not the case returns true but in a clearer and more concise way that could give us the option to add totally disparate test statements in one switch.
the reason it works is probably that the case expression evaluated is interpreted as a true or false value and then checked against the main -
switch(true)
You can't the case need to single value, that's compared to switch expression, but you can put multiple cases to execute the same code:
switch (field) {
case 'Yes':
case 'yes':
case 'YES':
msg = "FOO\n";
break;
case 10:
msg = "BAR\n";
break;
}
but in order to use test as case you can pass true to switch (I found that trick in some open source project):
switch (true) {
case field.test('Yes'):
msg = "FOO\n";
break;
case field == 10:
msg = "BAR\n";
break;
}
but this is the same as if/else
Note: you're using test() incorrectly, it's a method of a regex object, so you need /Yes/.test(field) rather than field.test('Yes'). Anyway...
If you've only got two cases as shown then I'd use an if/else/else if structure:
var field = $(this).val();
var msg;
if(/Yes/.test(field)) {
msg = "FOO\n";
} else if (field === 10) {
msg = "BAR\n";
}
If you need to add additional cases I'd just add extra if else {} branches on the end.
If you have several specific numeric cases you might consider putting them in a switch with the regex tests in a default at the end:
switch (field) {
case 10:
msg = "BAR\n";
break;
case 30:
msg = "whatever\n";
break;
case 50:
msg = "hi\n";
break;
default:
if (/Yes/.test(field)) {
msg = "FOO\n";
else if (/No|N|False|/i.test(field)) {
msg = "blah\n";
}
break;
}
The switch (true) option you alluded to in the question is really just a messier version of an if/else/else if, so it doesn't really make sense unless you have some fall-through cases:
switch(true)
case /Yes/.test(field):
case /Y/.text(field):
case /Whatever/.text(field):
msg = "FOO\n";
break;
case field == 10:
msg = "BAR\n";
break;
}
...and even then an if with multiple conditions joined by || arguably just as tidy with appropriate newlines, and combining multiple regexes into a single one is probably a lot neater.

Categories

Resources