Thursday, November 24, 2011

Local Variables and Variable Hoisting

The other day I ran across a few interesting features of JavaScript variable scopes.  Consider this code:


function doSomething({
    var 1;
    if (true{
        var 2;
        alert(a);
    }
    
    alert(a);
}

doSomething();



What would you expect?  If you are used to coding in a C like language, you would expect the first alert to be 2 and the second to be 1.  In JavaScript however this is not the result.  We get 2 for both alerts.  How come?


It turns out that JavaScript has no concept of "block-level" scoping (specific to the if block in this example).  Variables are either globally scoped or they are function scoped.  That means that even though we are in an if-block, we are still using the same scope as we were before entering the block.  So in our example the variable "a" is re-declared and assigned to 2, and it continues to be in scope after leaving the function, and will still be available until the function ends.


Here is a jsFiddle if you would like to play with it.


Reading about this led me to another interesting topic concerning variable scopes.  Look at this code:


1;
function doSomething({
    alert(a);
    var 2;
    alert(a);
}

doSomething();



To start we have a global variable named a which is assigned the value of 1.  Then when doSomething is called the alert displays the global variables value, a function level variable is created and assigned 2, which is then alerted.  Right?  Nope...


The first alert displays "undefined" while the second is 2.  Why doesn't the first fall back to the global variable?  This is due to the way JavaScript handles declarations.  They are automatically "hoisted" to the top of the function, leaving code that looks would look like this:


1;
function doSomething({
    var a;

    alert(a);
    2;
    alert(a);
}

doSomething();




Now it makes sense why we would get an "undefined".  The function scoped variable is completely hiding the global one, and it hasn't been assigned yet.  This is an important point... declarations are hoisted but assignments are not.  


Again, here is a jsFiddle with the scenario.  


Ben Cherry also has a good blog post about this issue.  






Wednesday, November 2, 2011

The debugger statement

The debugger statement in JavaScript will cause a debugger (like FireBug or the Chrome developer tools) to pause execution just as if there was a breakpoint at that line.  This is most useful when you have dynamically generated code or whenever you don't have a chance to set a breakpoint on a line before the code executes.  

Simple example:
var a = 44;
debugger;
alert(a);

In this case the debugger (if open) will pause before the alert is shown.  

Here are the MDN docs for the debugger statement.