Switch statement only returns the default case - javascript

Can someone help me understand, why is my switch case returning the default value. Even when I change all values it only returns the default at first I thought it was a hoisting issue in my code but after debugging it's I found it's the statement, it ignores all other cases. (p.s please don't be mean I just want to understand, the other examples I've seen aren't simply explained and don't have much up votes so I did try.)
var shippingMethod = document.querySelector("[name=r_method]:checked").value;
var shippingChoice;
switch(shippingMethod) {
case "usps":
shippingChoice = 2;
break;
case "ups":
shippingChoice = 3;
break;
default:
shippingChoice = 0;
break;
}
console.log(shippingChoice);

I would suggest adding an if statement to verify there is a value for shippingMethod. As well, when querying for the value, make sure to include quote ("") around the value of the name.
var shippingMethod = "default";
var shippingChoice;
if (document.querySelector('[name="r_method"]:checked') != null)
{
shippingMethod = document.querySelector('[name="r_method"]:checked').value;
}
switch(shippingMethod) {
case "usps":
shippingChoice = 2;
break;
case "ups":
shippingChoice = 3;
break;
default:
shippingChoice = 0;
break;
}
console.log(shippingChoice);

Related

Variable assignment within return statement, is it legal?

Is there any difference between 2 blocks of code below?
I would like to know which is the best practice. Is it legal to declare a new variable within a return statement like so in Block 2?
Block 1:
function caseInSwitch(num) {
let answer = "";
switch (num) {
case 1:
return answer += "alpha";
case 2:
return answer += "beta";
case 3:
return answer += "gamma";
case 4:
return answer += "delta";
}
}
console.log(caseInSwitch(3)); //output gamma
console.log(answer); //output gamma
Block 2:
function caseInSwitch(num) {
switch (num) {
case 1:
return answer = "alpha";
case 2:
return answer = "beta";
case 3:
return answer = "gamma";
case 4:
return answer = "delta";
}
}
console.log(caseInSwitch(3)); //output gamma
console.log(answer); //output gamma
As you can see, I have tried both which yield the same result in the console.
I think you can do as the following. There is nothing like legal. Do the most compatible way.
function caseInSwitch(num) {
let answer = "";
switch (num) {
case 1:
answer += "alpha";
break;
case 2:
answer += "beta";
break;
case 3:
answer += "gamma";
break;
case 4:
answer += "delta";
break;
}
return answer;
}
In Block 1, Your code is concatenated two strings together wherein Block 2 your code is assigning value to the variable. I suggest go with Block 2 because Block 1 is not the best practice.
In my opinion neither are a great practice.
Both options use multiple return paths, which should only be done with caution.
Your second option uses an undeclared variable which is therefore a global variable. Gobal variables are bad practice: Why are global variables considered bad practice?
Further more, not all paths return a value, again this is considered a bad practice, what should your function return if the parameter is invalid? It should return something.
Melvins answer is pretty much how I would do it but I wouldn't concatenate the string.
function caseInSwitch(num) {
let answer = "";
switch (num) {
case 1:
answer = "alpha";
break;
case 2:
answer = "beta";
break;
case 3:
answer = "gamma";
break;
case 4:
answer = "delta";
break;
}
return answer;
}
console.log("1 " + caseInSwitch(1));
console.log("7 " + caseInSwitch(7))
Other options could be to drop the switch statement and use an array or associative array
function fromArray(num) {
let answers = ["alpha", "beta", "gamma", "delta"];
return (typeof answers[num-1] === 'undefined') ? "Not Found" : answers[num-1];
}
function fromAssocArray(num) {
let answers = {1:"alpha", 2:"beta", 3:"gamma", 4:"delta"};
return answers.hasOwnProperty(num) ? answers[num] : "N/A";
}
console.log("1 " + fromArray(1));
console.log("7 " + fromArray(7));
console.log("---------- Associated Array Below --------------");
console.log("1 " + fromAssocArray(1));
console.log("7 " + fromAssocArray(7));

Creating a unit conversion method for the number prototype

I am currently trying to create a unit conversion for metric and English scale as a method for the number prototype. Heres my code:
Number.prototype.UnitConversion = function (units){
switch (units){
case "Metric":
this = this/100;
return this;
case "English":
this = this/12;
return this;
}
}
var a = 5;
alert(a.UnitConversion("Metric"))
However I get a left side invalid argument error. Why is that?
this is immutable in JavaScript, meaning you cannot reassign it, see: this SO post. However, you could simply return the value of some calculation done on it:
Number.prototype.UnitConversion = function(units) {
switch (units){
case "Metric":
return this/100;
case "English":
return this/12;
default:
return;
}
}
var a = 5;
console.log(a.UnitConversion("Metric"))
Its because an unexpected assignment to this. Maybe try a more readable, clean solution? Something like this:
Number.prototype.UnitConversion = function (units){
let conversion;
switch (units){
case "Metric":
conversion = this/100;
break;
case "English":
conversion = this/12;
break;
//always add a default case
}
return conversion;
}

Switch is not properly working in javascript

I have a switch statement which has several cases. These cases compare values and assign a text to a variable. But when I try to execute this switch, it always executes the default case. But my condition is true.. Why?
Here is my value
Apartment
Here is my code
var rental_cat = $('#rentals_type').val();
alert(rental_cat);
var rental_type = "";
switch (rental_cat) {
case (rental_cat == "Apartment"):
rental_type='daily';
alert(rental_type);
break;
case (rental_cat == "Office"):
rental_type='work_daily';
alert(rental_type);
break;
default:
rental_type='other';
alert(rental_type);
break;
}
When I execute this switch, it always gives me "other"
Remove the conditional expression inside the "case" clause.
Try this:
var rental_cat = $('#rentals_type').val();
alert(rental_cat);
var rental_type = "";
switch (rental_cat) {
case "Apartment":
rental_type='daily';
alert(rental_type);
break;
case "Office":
rental_type='work_daily';
alert(rental_type);
break;
default:
rental_type='other';
alert(rental_type);
break;
}
switch (rental_cat) {
case (rental_cat == "Apartment"):
is equivalent to
switch (rental_cat) {
case true:
which in turn is equivalent to
if (rental_cat === true)
You don't put a condition in the case, the condition is created as an equality check between the switch and the cases, so it should be like this instead:
switch (rental_cat) {
case "Apartment":
a switch is not the right structure to deal with this problem. Here I'd recommend a map:
var rentalTypesByCat = {
DEFAULT: "other",
"Apartement": "daily",
"Office": "work_daily",
}
var rental_cat = $('#rentals_type').val();
console.log("rental_cat:", rental_cat);
var rental_type = rentalTypesByCat[rental_cat] || rentalTypesByCat.DEFAULT;
console.log("rental_type:", rental_type);
or if you need it a bit more explicit (for example because some of your mapped values may be falsy themselves):
var rental_type = rentalTypesByCat[rental_cat in rentalTypesByCat? rental_cat: "DEFAULT"];
console.log("rental_type:", rental_type);

Switch Case Regex Test

var path = location.pathname;
switch(path){
case (/\/memberlist/).test(path) :getCSS('url-22.css'); break;
case (/\/register/).test(path): getCSS('url-6.css'); break;
case (/buy-credits/g).test(path): getCSS('url-7.css'); break;
case (/\/?u(\d+)friends$/).test(path): getCSS('url-8.css'); break;
case (/\/privmsg/).test(path): getCSS('url-9.css'); break;
case (/\/?u(\d+)wall$/).test(path): getCSS('url-4.css'); break;
}
function getCSS(url,media){
var a = document.createElement('link');
a.href=url;
a.media= media || 'screen';
a.rel="stylesheet";
return (document.getElementsByTagName('head')[0].appendChild(a));
}
That is my code, and for some reason it's not running the function that should run. For testing purpose we could change var path="/memberlist" and it still won't run. Can someone explain to me why this won't run. Don't really use switch statements
change
switch(path){
to
switch(true){
as you can see in thread I'm reffering to in comment.
None of the answers posted show a correct method to use a RegExp pattern in a switch case so I thought I'd post:
switch (myVar) {
case 'case1':
/...do work
break
case /[a-z]*/.test(myVar) && myVar:
/...regex match, do work
break
}
switch-case doesn't work that way.
regex.test() method returns a boolean (true/false) and you are comparing that against the input string itself which will not be true for any of the case statement.
You need to convert switch-case into multiple if / else if / else block to execute your logic.
Just for the record, the switch case could be rewritten to:
getCSS(
/\/memberlist/).test(path) && 'url-22.css' ||
/\/register/).test(path) && 'url-6.css' ||
/buy-credits/g).test(path) && 'url-7.css' ||
/\/?u(\d+)friends$/) && 'url-8.css' ||
/\/privmsg/).test(path) && 'url-9.css' ||
/\/?u(\d+)wall$/).test(path) && 'url-4.css' ||
'default'
);
Or rewrite getCSS, using a helper object
var path2url = {
css: [
{re: /\/register/, css: 'url-22.css'},
{re: /buy-credits/g, css: 'url-6.css'},
{re: /\/?u(\d+)friends$/, css: 'url-8.css'},
{re: /\/privmsg/, css: 'url-8.css'},
{re: /\/?u(\d+)wall$/, css: 'url-4.css'}
],
getURL: function(path) {
var i = this.css.length;
while (--i) {
if (this.css[i].re.test(path)) {
return this.css[i].css;
}
}
return null; // or something default
}
};
function getCSS(path,media){
var a = document.createElement('link');
a.href= path2url.getURL(path); // <=
a.media= media || 'screen';
a.rel="stylesheet";
return (document.getElementsByTagName('head')[0].appendChild(a));
}
Have a look
switch(str){
case (/(abc|xyz)/.test(str) ? str : false):
// Do some stuff
break;
default:
// Do default stuff
}

Can someone explain how JSON parsers work without using eval at all?

I can't comprehend how it works without using eval - what's the secret behind this?
Edit: Could someone present a trivial example of how the tree structure is converted to an object?
JSON has a well defined grammar which is used to construct a tree which is then converted to an object.
Get Douglas Crockford's book, Javascript: the Good Parts. Appendix E includes code implementing a JSON parser. It does not use eval.
I don't know specifics but it's not really hard. Just a smart combination of reading characters and substrings, interpreting what they mean and building up an array of data while you do it. Like any other parser.
There is no secret. How do you think eval() is implemented? It uses the same techniques that you would have to use if you had to parse JSON data, i.e. effectively reimplement part of eval().
Take a look at my parser for a good idea. It isn't perfect but the code is pretty easy to follow.
public static JsonStructure Parse(string jsonText)
{
var result = default(JsonStructure);
var structureStack = new Stack<JsonStructure>();
var keyStack = new Stack<string>();
var current = default(JsonStructure);
var currentState = ParserState.Begin;
var key = default(string);
var value = default(object);
foreach (var token in Lexer.Tokenize(jsonText))
{
switch (currentState)
{
case ParserState.Begin:
switch (token.Type)
{
case TokenType.BeginObject:
currentState = ParserState.Name;
current = result = new JsonObject();
break;
case TokenType.BeginArray:
currentState = ParserState.Value;
current = result = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Name:
switch (token.Type)
{
case TokenType.String:
currentState = ParserState.NameSeparator;
key = (string)token.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.NameSeparator:
switch (token.Type)
{
case TokenType.NameSeparator:
currentState = ParserState.Value;
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.Value:
switch (token.Type)
{
case TokenType.Number:
case TokenType.String:
case TokenType.True:
case TokenType.False:
case TokenType.Null:
currentState = ParserState.ValueSeparator;
value = token.Value;
break;
case TokenType.BeginObject:
structureStack.Push(current);
keyStack.Push(key);
currentState = ParserState.Name;
current = new JsonObject();
break;
case TokenType.BeginArray:
structureStack.Push(current);
currentState = ParserState.Value;
current = new JsonArray();
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.ValueSeparator:
var jsonObject = (current as JsonObject);
var jsonArray = (current as JsonArray);
if (jsonObject != null)
{
jsonObject.Add(key, value);
currentState = ParserState.Name;
}
if (jsonArray != null)
{
jsonArray.Add(value);
currentState = ParserState.Value;
}
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
currentState = ParserState.End;
break;
case TokenType.ValueSeparator:
break;
default:
throw new JsonException(token, currentState);
}
break;
case ParserState.End:
switch (token.Type)
{
case TokenType.EndObject:
case TokenType.EndArray:
case TokenType.ValueSeparator:
var previous = structureStack.Pop();
var previousJsonObject = (previous as JsonObject);
var previousJsonArray = (previous as JsonArray);
if (previousJsonObject != null)
{
previousJsonObject.Add(keyStack.Pop(), current);
currentState = ParserState.Name;
}
if (previousJsonArray != null)
{
previousJsonArray.Add(current);
currentState = ParserState.Value;
}
if (token.Type != TokenType.ValueSeparator)
{
currentState = ParserState.End;
}
current = previous;
break;
default:
throw new JsonException(token, currentState);
}
break;
default:
break;
}
}
return result;
}
trivial example of how to convert a string with json into an object without eval:
var txt='[\'one\',\'two\']';
var re1='(\\[)'; // Any Single Character 1
var re2='(\\\'.*?\\\')'; // Single Quote String 1
var re3='(,)'; // Any Single Character 2
var re4='(\\\'.*?\\\')'; // Single Quote String 2
var re5='(\\])'; // Any Single Character 3
var p = new RegExp(re1+re2+re3+re4+re5,["i"]);
var m = p.exec(txt);
if (m != null)
{
var c1=m[1];
var s1=m[2];
var c2=m[3];
var s2=m[4];
var c3=m[5];
return [s1, s2];
}
return null;
yes this a horrible way to do it, but it does what it claims for that string :p
JSON is a native representation of data. It is simply a creative implementation of JavaScript's built-in object format. Being native, it doesn't need to be "parsed" (in the sense that the programmer needs to worry about doing it) at all.

Categories