Firebug debugging confusing in JavaScript switch statement - javascript

I have the following switch statement in JavaScript :
switch(scrollable.direction){
case "top" :
break;
case "left" :
break;
case "right" :
scrollable.select("."+lineCssClass).invoke("setStyle", {float: "right"});
break;
case "bottom" :
alert("Bottom scrolling not implemented yet ! Sorry !");
return;
}
(the "invoke" bit is prototype.js, but it's no relevant to the question anyway)
It is inside a function. I want that if the value is "bottom" a message is displayed and the method execution stops.
The problem is that if the value is e.g. "top", the break is executed, but the execution jumps to the return; statement instead of exiting the switch statement.
I actually solved the problem by adding an additionnal break; after the return, which is actually dead code since it can never be executed.
But I would be curious to know why it executed the "return" in the first place ?
Edit: I am sorry, the "return" wasn't actually executed. I was stepping through the code using Firebug and it actually stepped on and highlighted the "return" line, but it wasn't executed.
There are other problems in my code that cause it not to work as expected, and I was wrongly blaming this.

My bet is that your scrollable.direction is giving you a worng value that is not a real direction.
Add a default clause to your switch statement (as you should always do, btw) to check it out
switch(scrollable.direction){
/*...*/
case "bottom" :
alert("Bottom scrolling not implemented yet ! Sorry !");
return;
default:
console.log(scrollable.direction, 'is not a direction');
break;
}

As I said in the edit I made to the question, the problem was actually not that the return; was executed, but that Firebug gave the impression it was when I went step by step through the switch statement.
Alsot, after some more tests, I can reproduce this weird thing only when I enclose the switch/case statement in a try block.
As missingno suggested I will leave this question in case other people are confused by this behaviour of Firebug.

Similar sort of issue occurred with me while using Firebug but on the IF statement.
if(multiship == true)
{
// do something
}
else
{
// do something
}
The debugger showed that the script execution took the if path instead of having multiship variable equal to false.

Related

Weird Javascript/JQuery Conditional Statement Behavior

I ran across an interesting problem today (Firefox 44). I have a conditional statement that is evaluating the else if statement after evaluating a 'true' if statement. Take an example:
The initial state of .dataRow is collapsed. When a dataRow is clicked the first condition is found to be true and the class is changed to expanded. Next the else if statement is evaluated and the class is changed back to collapsed because it changed to expanded in the previous condition! Why in the world would the else if statement be evaluated after the first condition is found true?
$("div").on("click", "div.dataRow", function(){
if ($(this).hasClass("collapsed"))
{
$(this).removeClass("collapsed").addClass("expanded");
}
else if($(this).hasClass("expanded"))
{
$(this).removeClass("expanded").addClass("collapsed");
}
});
I had to put return statements in the conditions to get the function to work properly.
$("div").on("click", "div.dataRow", function(){
if ($(this).hasClass("collapsed"))
{
$(this).removeClass("collapsed").addClass("expanded");
return false;
}
else if($(this).hasClass("expanded"))
{
$(this).removeClass("expanded").addClass("collapsed");
return false;
}
});
EDIT
Here is a simplified reproduction of the problem jsFiddle
I am not into removeClass and addClass of jQuery right now. But each "else if" block condition is evaluated. As you add the class in the first block, the second condition is always true after that.
If you have only two conditions, I would advise you to only use "else". That would protect the second block from being executed, if the first was executed.

How are labels used with statements that are not a loop?

According to the ECMAScript 5.1 spec, section 12.12, any statement can be labelled - and in a brief test my browser accepted a label before any statement. The spec also states that labels are used exclusively with break and continue statements, and a quick test revealed that those statements throw an "undefined label" error if the label they reference does not refer to a loop that contains them.
So my question is this: what are labels for statements that are not loops used for? Is there some context in which break or continue can reference a label that is not a loop?
Apparently the break and continue statements can be used within any statement:
http://docstore.mik.ua/orelly/webprog/jscript/ch06_11.htm
In which case things like this become legal:
function show_alert()
{
label:
{
break label;
alert("Hello! I am an alert box!");
}
alert("hi");
}
When show_alert() is called, only the "hi" alert is shown.
As far as I know, this is the only use of the {} code blocks, other than for code styling. (there was a question on here about that, and noone could come up with anything other than readability, but I can't find it now...)
Yes you can label any statement. You just need to put the statement in curly braces, i.e.
{start:var a=1;}
this will not show undefined label error.

simple javascript if not working

I'm new to javascript and am having issues with a seemingly simple if/else statement.
Can anyone let me know why the below isn't working please (Im pulling my hair out)
var is_expanded = false;
if (is_expanded==false) {
alert('no');
is_expanded = true;
} else {
alert('yes');
}
I always get the 'no' alert (I never get to the else part).
Cheers for any help.
This is working as designed.
The condition is checked when you say if. It then goes into the correct block, in this case the one that alerts "no".
The condition does not get re-evaluated after the block has been executed. That's just not how the if statement works, not in any language I know.
Depending on what you want to do, there are other patterns and constructs that can help you, for example a while loop. Maybe show the real use case that you need this for.
That's because is_expanded always equals false because you've set it as false BEFORE the if statement.
else will not fire unless is_expanded equals true before the if statement.
You previous line of code says var is_expanded = false;
which means if (is_expanded==false) will always evaluate to true.
So that is exactly what you are getting as output. What did you expect?
Next time when your same method is called, the value for is_expanded is again reset to false due to your first line of code. Then again it will alert no
That's normal. You have set the variable is_expanded to false so in the if statement you are always entering the alert('no'); part. After you set the variable to true but there is no longer any if statement executed.
var is_expanded = false;
if (is_expanded==false) {
alert('no');
is_expanded = true;
} else {
alert('yes');
}
Congratulations! Your code is working perfectly, so stop pulling your hair out.
The nature of IF/ELSE is that only one of them fires per pass. So, your code checks whether is_expanded is FALSE. If it's false, it will run the IF part. If not, it'll run the ELSE part.
Just read it like english.
If something, do this. Otherwise, do something else
Even if you change the value of the variable inside one of the blocks, it won't matter because once it checks the block, it moves on.

Would it be ridiculous to use a switch statement to handle irc server codes?

There are quite a few of IRC server codes
I am working on a small IRC client for Adobe AIR, and I started out by supporting only a few of these initially, and then a switch statement didn't seem like a bad idea. But as I support more and more, the switch statement is getting longer and it feels like it's a little out of control. One issue is that I've kept the low level IRC handling code in a file on its own so that it can be reused. I would like to keep everything in one file. Another issue is that code blocks in the switch statements currently assume to be part of this IRC class and there's frequent use of the this statement. Making changes now would be a lot of work and introduce regressions. The only problem really is my distaste for a long switch statement, otherwise you know it works, and it's kind of easy to read, but not really making it more difficult to maintain. But it's such a long switch statement. And the function that contains the switch statement is obviously long too. ://
One thing I sometimes do in lieu of a switch is that I define functions that are named after the value the switch evaluates. Instead of a switch:
switch ( val ) {
case: "alert":
alert( "yo" );
break;
}
I check to see if a method exists in scope and execute it:
obj.alert = function ( ) {
alert( "yo" );
}
if ( val in obj && isFunction( obj[ val ] ) ) {
obj[ val ]( );
}
But again in this case I've feel like there's a high risk in regressions and I'm not sure it's worth the effort only to avoid having a long switch statement, for the sake of its length.
Why don't you keep a hash (a JavaScript {} object) with the code as the key and the function as the value? Then, for small pieces of code you could use an anonymous function, and for bigger pieces of code you could just have a reference to an already written function. I don't know anything about IRC, but here's a small example:
var CodeHash = {
001: function() { /* Do something... */ },
002: BigImportantObject.someFunction
}
Kind of a bad example, but you get the idea.
Edit: If you believe that you can maintain such a long switch statement easily and without problems, then I think it's ridiculous to rewrite your program just to remove the switch. But I know that I, personally, would much rather maintain a hash table like above than a huge switch statement, for many reasons. So it's up to you. Seems like a rhetorical question if you keep insisting that the only reason you'd rewrite your code is to get rid of the switch statement.
why not keep the switch in a parameter file with predefined exit points along with their arguments
read the file at the startup and keep in in memory

Javascript: What's more efficient, IF block or TRY/CATCH?

I'd love some other opinions on what's more efficient in this code. Basically in the following code, there's a setInterval loop and I need 4 requirements to be true before the code runs in the loop. So in v.1 I wrote an if statement checking all 4. Worked fine.
Then I switched to just using try/catch, with the code I want to execute sitting in try{}. The logic was that during each loop, an exception would be generated but suppressed for each invalid condition. On the final loop where all conditions are true, the code executes and clears the interval.
Either works. I like the try/catch method because there's less conditional code that I need to write and worry about breaking. But I'm worried that try/catch is really inefficient, especially in a setInterval() loop hitting at 100ms. What are some opinions of other bright minds here on SO?
Try/Catch
var intvar = setInterval(function(){
try{
clearInterval(intvar);
jQuery('#'+nav[pageid].t1+'>a').replaceWith(jQuery('<span>'+jQuery('#'+nav[pageid].t1+'>a').text()+'</span>'));
//set display classes for nav
jQuery('#'+nav[pageid].t1).addClass('selected').find('#'+nav[pageid].t2).addClass('subselect'); //topnav
jQuery('#'+nav[pageid].t3).addClass('selected').find('#'+nav[pageid].t4).addClass('subselect'); //leftnav
}catch(err){}
},100);
IF Block
var intvar = setInterval(function(){
if(typeof jQuery == 'function' && typeof nav == 'object' && typeof pageid != 'undefined' && typeof document.getElementById('leftnav') == 'object'){
clearInterval(intvar);
jQuery('#'+nav[pageid].t1+'>a').replaceWith(jQuery('<span>'+jQuery('#'+nav[pageid].t1+'>a').text()+'</span>'));
//set display classes for nav
jQuery('#'+nav[pageid].t1).addClass('selected').find('#'+nav[pageid].t2).addClass('subselect'); //topnav
jQuery('#'+nav[pageid].t3).addClass('selected').find('#'+nav[pageid].t4).addClass('subselect'); //leftnav
}
},100);
Exceptions should be used for exceptional circumstances (i.e. things that you don't expect to happen normally). You should not, in general, use exceptions to catch something that you can test for with an if statement.
Also, from what I understand, exceptions are much more expensive than if statements.
Use the if statement. I don't know what the overhead is for a TRY/CATCH, but I suspect it's far greater than evaluating a boolean expression. To hit the TRY/CATCH you will have to: execute a statement, generate an error [with that associated overhead], log the error (presumably), made a stacktrace(presumably), and moved back into the code. Additionally, if you have to debug code near those lines the real error could get obfuscated with what you are TRY/CATCHing.
Furthermore, it's a misuse of TRY/CATCH and can make your code that much harder to read. Suppose you do this for longer or more obfuscated cases? Where might your catch end up?
This is referred to as Exception handling
EDIT: As commented below, you only take the runtime performance hit if you actually cause an exception.
The other answers are correct, try/catch is for exceptional circumstances and error handling. if conditions are for program logic. "Which is faster?" is the wrong question.
A good rule of thumb, if you're doing nothing with the exception, it's probably not an exception!
To figure out which to use, let's break down your if condition.
typeof jQuery == 'function' Is the jQuery() function defined?
typeof nav == 'object' Does the nav global variable contain an object?
typeof pageid != 'undefined' Is the pageid global variable defined?
typeof document.getElementById('leftnav') == 'object' Does the document contain a leftnav element?
The first is clearly an exception. You ain't getting far without a jQuery() function.
The second is also an exception. You're not going anywhere without a nav object.
The third is an exception. You need a pageid to do anything.
The fourth is probably logic. "Only run this code if there is a leftnav element". It's hard to tell because the rest of the code doesn't reference a leftnav element! Only the comments do, a red flag. So it's probably a programming mistake.
So I'd probably do this (with apologies if I'm butchering jQuery):
var intvar = setInterval(function() {
// If there's no leftnav element, don't do anything.
if( typeof document.getElementById('leftnav') != 'object') {
return;
}
try {
clearInterval(intvar);
jQuery('#'+nav[pageid].t1+'>a')
.replaceWith(jQuery('<span>'+jQuery('#'+nav[pageid].t1+'>a').text()+'</span>'));
//set display classes for nav
jQuery('#'+nav[pageid].t1)
.addClass('selected')
.find('#'+nav[pageid].t2)
.addClass('subselect'); //topnav
jQuery('#'+nav[pageid].t3)
.addClass('selected')
.find('#'+nav[pageid].t4)
.addClass('subselect'); //leftnav
}
catch(err) {
...do something with the error...
}
},100);
...but I'd really examine if the leftnav element check is applicable.
Finally, I can't help but comment that this "function" is working with global variables. You should instead be passing nav and pageid into the function in order to maintain encapsulation and your sanity.
I would write the following code:
var startTime = (new Date()).getTime();
for (var i=0; i < 1000; ++i) intvar();
var endTime = (new Date()).getTime();
alert("Took " + ((endTime - startTime) / 1000.0) " seconds");
Then I would try both versions of intvar and see which runs more quickly. I'd do this myself but I don't have the page layout you do so my code wouldn't work.
Some stylistic comments - it doesn't seem necessary to test that jQuery is a function. If it isn't, your webpage is likely messed up such that not running the intvar code will not help you. If you rarely expect the exceptions to be thrown, I'd use the try/catch.
For the provided example where you are wrapping a try/catch around a block of code that should always run anyway (unless if something horrible happens), it is good form to use try/catch. An analogy for you: do you always test "Is the sky Blue?" in your if statement, or would you wrap it in a try/catch that is triggered only when the sky happens to turn Green.
Use the If statement method if you are dealing with user provided input or if the chances of a function not existing is much higher due to something else happening in the code.
Keep in mind that if you don't trigger the exception you don't have any unwinding or backtracking across code. In the example the catch will only execute if something is wrong (jQuery is missing or some such thing), however the if statement method has an evaluation happening on EVERY SINGLE CALL to that function - you shouldn't do more work than you have to.
To directly answer the question, as everyone else has, the try..catch is likely going to be more expensive if there actually is an error.
To point out some additional errors in the code beyond what others have already pointed out:
These two codes are not at all equivalent. To explain, even though the codes appear to do the exact same thing, they do not.
In the case of the if() check, NONE of the code is executed. In the case of the exception handler, each line of code inside the exception handler will be executed. SO, what happens if the error occurs in the second, or the third line? Then you've got something completely different happening in your code than what you get if you check the conditions before executing any of it.
Aside from the answers given, I want to add some thoughts on this subject.
Exceptions that are unforeseen, i.e. the runtime throws an exception, should not be caught with try ... catch because you want to read the message that is thrown in the console.
Try ... catch should IMO be thrown when an exception occurs that your application can foresee in your application logic and you want to perform some custom actions when they do. I.e. you want to be descriptive about it being an exception, and it's not part of the happy flow of the application logic.
For example, you could have a method that validates user input so you could have an isValid method that returns a boolean in which case you would use if ... then.
On the other hand if your performing a certain process, and you know that a certain exception can occur that interrupts the happy flow and you want to handle this, I feel that it is better to throw an exception.
As abstract example, you could have methods that implements some business rules.
Instead of validating every business rule for validity, you could have one custom Exception containing dynamic metadata that can be thrown by each of these methods when validity is breached and handle them appropriately, and continue the happy flow otherwise.
This would translate into something like:
throw new BusinessValidationException(TAG, 'Reason for the validation');
Which IMO is much more descriptive than:
if (!checkValidityBusinessRule())
// doSomething
For a series of business rules.
As for the example, it's my humble opinion that this check shouldn't be happening in the first place and that the given checks are true by default for implementing the method.
if(typeof jQuery == 'function' && typeof nav == 'object' && typeof pageid != 'undefined' && typeof document.getElementById('leftnav') == 'object')
What it means is that you must declaratively ensure that given conditions are true before invoking the given method with side-effects, taking away the necessity to perform the checks at all.
If it so happens that one of the conditions is false, then it will throw an exception to the console, which is actually what you want because as a developer it means that something in your application logic or lifecycle is broken.
My 2 cents, I hope they make sense.

Categories