JavaScript – A Different Beast, Part-4: Scopes and Scope Chain

Scope Chain

The outermost scope in JavaScript is called the global scope. Any code that you write in an HTML page within the <script> and </script> tags goes into the global scope. Local scopes arise only when variables or functions are written inside another function. See code-2.8 for an example.

//Code – 2.8:&nbsp; Global vs. Local Scopes
function f2(){
    var x = 'inner2'; //local to f2
    var f2sVar = 'f2'; //local to f2
    console.log(x);&nbsp;   //the local x
    console.log(globalVar); //global is accessible
    console.log(f2sVar); //local
    try {
        console.log(f1sVar); // Not in local or global scope.
    } catch(e) {
        console.log("Doesn't work - " + e);
    }
}

function f1(){
    var x = 'inner1'; //local to f1
    var f1sVar = ‘f1’; //local to f1
    console.log(x); //local x
    f2();
}

var x&nbsp; = 'global';  //global context
var globalVar = 'globalVariable'; //global context
console.log(x); //prints global
f1();

/*------------- Output ------------------
global
inner1
inner2
globalVariable
f2
Doesn't work - ReferenceError: f1sVar is not defined
*/

Figure-3 below shows the lexical scopes established by this code. As can be seen from the figure, there are three distinct scopes in this code – the global scope and two local scopes one for each function. Also, each scope has a link to the scope in which it was created. i.e. the created scope always has a link to the creator scope and can  form a scope-chain. The example here has two scope chains, and each chain has two elements each – the function’s scope and the global scope. (It is easy to see that the code-2.6 we saw earlier creates a scope chain with three elements.) Variable/function resolution in JavaScript works by searching in the scope chain from the innermost scope to the outermost one. That is why both the functions f1 and f2 has access to the global variable – ‘global’. The variable ‘x’ is also accessible, but it is getting overridden by the local definitions of x in each of the local scopes.

Scope Chain for Code-2.8
Scope Chain for Code-2.8

Note to readers: Please note that the scope chain is different from the execution stack. When JavaScript interpreter executes code, it creates an Execution Stack with only one element – a Global Execution Context. When it encounters a function-call, a new Execution Context is created and pushed into the stack. Each function is executed in its own Execution Context. For example, in the previous code, when the interpreter is executing the code inside function f2, the execution stack is Global Execution Context followed by f1’s Execution Context which is followed by f2’s Execution Context, but scope chain remains the same as in Figure-1. And that is the reason why f1’s local variables are not accessible inside f2, despite f2 being below f1 in the execution stack. However, the current Execution Context is always added to the top of the scope chain. I will not be discussing the execution stack or the execution context any more in this tutorial. Too much details gets in the way of learning. For those who want to understand more about execution stack, please see the references at the end of this tutorial.

Code-2.9, below, is for printing our address ;-). It is slightly more complex since its scope chain has 4 levels in it. See adjacent figure. The variables are shown in rectangles and the scopes are shown as ovals. From the scope chain, you can see how all the variables are accessible inside the innermost function.

//Code – 2.9:  4-level scope chain
function galaxy(){
    var vGalaxy = 'MilkyWay';
    function star() {
        var vStar = 'Sun';
        function planet() {
            var vPlanet = 'Earth';
            console.log([vUniverse,vGalaxy,vStar,vPlanet].join(' >> '));
        }
        planet();
    }
    star();
}
var vUniverse = 'Universe';
galaxy();

/*------------- Output ------------------
Universe >> MilkyWay >> Sun >> Earth
*/
Scope Nesting
Nested scopes for code-2.9

Note: All scope chains finally terminate at the global scope. And that is why global scope is, well, global; any function that you write will have access to the variables and functions defined in the global scope – all the more reason for you to avoid writing functions in global scope. Contain your code within your own scopes so that conflicts don’t happen. (See Module Pattern in Part-IV)

Scope chains are runtime structures which change during execution. The scope chain shown in the figure above is formed when the interpreter is executing code inside function planet. As soon the interpreter leaves the function planet, the planet-scope is removed from scope. Similarly, when the interpreter leaves the function star, the star-scope is also removed from the scope chain and so on.

Next topic in this series: Closures

Advertisements

About Rahul Mohan

Technical researcher interested in model-driven development of enterprise business applications. Passionate about web technologies and a huge admirer of open-source especially in the Java landscape. When I am not doing any of the above you can find me with my camera (www.flickr.com/photos/rahulmohan/) or listening to music. (In fact, the title of the blog is inspired by Led Zeppelin's Physical Graffiti. )

Posted on May 15, 2011, in JavaScript, Tutorial and tagged , , , , , , , . Bookmark the permalink. 5 Comments.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: