Getting Funky With Scopes and Closures
The most powerful thing about the JavaScript programming language are it’s scoping rules. In programming languages, scope is what makes the world go round. It defines the context in which the code executes. The context contains objects which are available to the code. To draw a real-world analogy: Say you’re in your living room, and you want to watch some television. You can, because the television is in your living room. But what if you’re in the kitchen?
Scopes can be chained to each other. This means that if some portion of the code is not available in the current scope, you’ll be able to find it somewhere else. If you’re in the kitchen, and it is chained to the living room via a door (as in my place), you can simply walk to the living room to watch television.
In JavaScript there is a variable scope chain. All objects are stored inside variables (and in JavaScript everything is an object). New scopes can only be created when you define a new function. The newly created scope will be chained to the scope it was created in. And for good measure there is a global scope, available right from the start. In most JavaScript implementations (read: browsers), this is the window object.
As I said, in JavaScript everything is an object. You could view the scope as an object as well: the variables you use are simply properties on this object. Normally you can’t access this scope object, it is implied by the language and everything is handled by the interpreter. There is, however, one exception to this rule. The window object acts as a public scope object. Let’s have a look:
var foo = 'bar';
window.baz = 'thud';
alert(window.foo); // alerts 'bar'
alert(baz); // alerts 'thud'
As you can see the foo variable is accessible by window.foo, just as the window.baz property is accessible by baz.
So how do we find the variables on the scope chain? First the JavaScript interpreter checks if the variable has been declared in the current scope (or: if the property exists on the hidden scope object). If not, it’ll check the chained scope. This process continues until the variable has been found, or until the window object has been reached and the variable hasn’t been declared even on that object. In this latter case an exception will be thrown.
This process makes it possible to use the same variable name in different scopes, effectively masking the other variables. There is one caveat in JavaScript though: unless you declare the variable with the var keyword it will be created in global scope.
By now it’s time for some examples:
var foo = 'bar'; // variable declared in global scope
function a() { // creates a new scope, chained to the global scope
alert(foo);
}
a(); // alerts 'bar'
function b() { // creates a new scope, chained to the global scope
foo = 'the quick brown fox'; // in which scope does the `foo` variable exist?
}
alert(foo); // alerts 'bar'
b();
alert(foo); // alerts 'the quick brown fox'
function c() {
var foo = 'thud';
alert(foo);
}
alert(foo); // alerts 'the quick brown fox'
c(); // alerts 'thud'
alert(foo); // still alerts 'the quick brown fox'
Of course we can chain more than two scopes together:
function d() { // what scope is this function chained to?
var foo = 'thud';
function e() { // creates a new scope, chained to the scope of `d()`
alert(foo);
}
e();
}
d(); // alerts 'thud'
Function e() has access to the scope of function d(). This is called a closure. As I said this is one of the most powerful things of JavaScript. This lets you do some really cool things. Ever wanted to create private methods in JavaScript? Now you can!
function A() {
function hidden() {
alert("I'm a private method!");
}
this.visible() {
alert("I'm a public method. I can also invoke `hidden()`.");
hidden();
}
}
var a = new A;
a.visible();
Up to you to figure out why this works.
This also lets us create Singleton objects:
var b = new function() {
this.hello = function() {
alert('Hello world!');
}
}
b.hello();
Or functions which have private methods in their scope:
var c = (function() {
function hidden() {
alert("I'm a private method!");
}
return function() {
alert("I'm a public method. I can also invoke `hidden()`.");
hidden();
}
})();
c();
This latter technique is referred to as Block Scope.
One thing to watch out for with these techniques are memory leaks. You can find more info about those by reading my Event Cache article. In any case, let that not be a discouragement! Closures are cool. Use them.



