Scope Chain in Javascript
To understand the scope chain you must know how closures work.
A closure is formed when you nest functions, inner functions can refer to the variables present in their outer enclosing functions even after their parent functions have already executed.
JavaScript resolves identifiers within a particular context by traversing up the scope chain, moving from locally to globally.
Consider this example with three nested functions:
var currentScope = 0; // global scope
(function () {
var currentScope = 1, one = 'scope1';
alert(currentScope);
(function () {
var currentScope = 2, two = 'scope2';
alert(currentScope);
(function () {
var currentScope = 3, three = 'scope3';
alert(currentScope);
alert(one + two + three); // climb up the scope chain to get one and two
}());
}());
}());
Recommended reads:
- JavaScript Closures
- Closures
Any function call in ECMAScript ( core language that JS is based on ) produces a separate execution context, which run individually from one another. Inside of each execution context, this
refers to the object in question, defaulting to whatever the function is attached to.
function foo() {
alert(this===window)
}
Would alert true, because the window is the object which owns the 'foo' method. Any variables defined in a function become accessed through that function's unique scope chain, environment.
function world() {
var name = 'global';
alert(name)
}
would alert 'global' obviously.
function world() {
var name = 'global';
(function() {
var name = 'country';
alert(name)
})();
alert(name)
}
In the latest example, when the first alert is invoked, Javascript determines that in the scope chain of the inner function that the identifier name
is defined, so it doesn't have to look up the scope chain to grab it.
In the second alert invocation, name
is also defined in the same context and alerts 'global';
function world() {
var name = 'global';
(function() { alert(name) })();
}
In this example, the name
identifier is not defined in the same context and thus it has to travel up the scope chain to the outer function where name is defined, and it alerts global.
Reference:
- http://www.digital-web.com/articles/scope_in_javascript/
- http://www.jibbering.com/faq/faq_notes/closures.html
I know it's an old post but it is still helpful for developers. I wanted to do it little different way as it would be more friendly for beginners to understand scope chaining. Here is my modified version of code:
var currentScope = 0; // global scope
function a () {
var currentScope = 1, one = 'scope1';
alert(currentScope);
function b () {
var currentScope = 2, two = 'scope2';
alert(currentScope);
function c () {
var currentScope = 3, three = 'scope3';
alert(currentScope);
alert(one + two + three); // climb up the scope chain to get one and two
}
c();
}
b();
}
a();