I just learned something very surprising about scope in Javascript from John Resig. Take a look at this very simple example:
Scope of Object Properties
var aObj, bObj;
var val = 'c';
function a() {
this.val = 'a';
}
a();
function b() {
this.val = 'b';
}
b();
bObj = new b();
aObj = new a();
console.log(aObj.val, bObj.val, val);
What output would you expect to find in the Javascript console? I thought I’d see a b c. Not so. The output is actually a b b. The implication of this is that properties defined within the context of functions (which are objects in Javascript) are actually placed in the global scope at the time the functions are called as well as locally in each function.
The danger in this behaviour is that an unaware programmer could rely on the global variable val defined at the beginning of the script without realizing that it has ultimately been hidden by b.val. This could lead to some serious head-scratching since it isn’t at all the behaviour I would have assumed.
How can we avoid the problem? Try this:
Revised Code
var aObj, bObj;
var val = 'c';
function a() {
var val = 'a';
this.getVal = function() {
return val;
}
}
a();
function b() {
var val = 'b';
this.getVal = function() {
return val;
}
}
b();
bObj = new b();
aObj = new a();
console.log(aObj.getVal(), bObj.getVal(), val, aObj.val, bObj.val);
This revised code outputs a b c undefined undefined. For the uninitiated, the above code uses closures to create real local variables. Another fix would be to avoid name collisions on variables you intend to be local to the functions a() and b(), but this is an inferior approach since errors will easily be introduced whenever the code is revised.
For a straight-forward explanation of closures, please try javascriptkit.com’s explanation of them. If you have any questions, please feel free to leave them in the comments.