Javascript - understanding scope
Since I’ve been digging into JQuery, I though that it would also be a good idea to write a little bit more about Javascript. In my (limited) experience, I’ve met many developers who say that they really know Javascript and that it’s a really simple language. The problem is that they have lots of trouble in understanding and explaining the basic concepts/feature of the language. I’m not really a Javascript expert, but I guess that sharing several of the gotchas I’ve tripped along the way won’t do any harm, right?
And that’s why I’ve decided to start a new series of posts which talks about several important concepts that you might find useful in your day to day use of JS. As you’ve probably guessed from the title, today we’ll be talking about scope.
Scopes might be tricky and, like Eric Lippert said, are sometimes confused with lifetime and declaration space. According to Eric, the scope of an entity is a region of program text in which it’s possible to refer to that entity by its unqualified name. To me, this is really good, clear and concise definition of scope.
In Javascript, scope is “defined” through functions (and not by blocks, like in C). Btw, variables defined outside a function are said to be defined on the global scope. Let’s start with a really simple example. What do you think will happen when you run the following code:
var globalMsg = "hello world!";
if (true) {
var globalMsg = "yes, I'm updating the global";
//is globalMsg redefined here? (1)
}
//and here? (2)
As I’ve said before, blocks don’t introduce scopes in Javascript. In practice, that means that the var declaration inside a block isn’t really introducing a new variable because there’s already a variable with that name in the current scope. Now, what would happened if we changed our code like this:
var globalMsg = "hello world!";
function sayHi() {
if (true) {
var globalMsg = "yes, I'm updating the global";
//what's the value of globalMsg? (1)
}
}
sayHi();
//and here? (2)
Since our if block is wrapped by a function and since function definitions do create a new scope in Javascript, then the globalMsg declared inside the block will indeed create a new variable which hides the global variable. Notice that the use of the var keyword important! If we’d missed it, then we would end up defining a variable in the current global scope:
<script type="text/javascript">
function sayHi() {
if (true) {
globalMsg = "yes, I'm updating the global";
//what's the value of globalMsg? (1)
}
}
sayHi();
//and here? (2)
If you run the previous snippet, you’ll notice that globalMsg is being defined in the global scope and that you can access it on line (2) (notice that its value was the one we’ve set up inside the function). If you run the previous code in a HTML page, then you’ve probably noticed a side effect of the global scope: global scope definitions are instantiated as fields of the window object (at least, on most modern browsers). If you don’t believe me, then run the next snippet:
var globalMsg = "Hello";
alert(window.globalMsg);
And I guess this covers the basic features of the language. In the next post of the series, we’ll wrap our discussion of scopes and we’ll talk about execution contexts. Keep tuned for more on Javascript.