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: Global vs. Local Scopes
function f2(){
var x = 'inner2'; //local to f2
var f2sVar = 'f2'; //local to f2
console.log(x); //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 = '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.
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
*/
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
Pages: 1 2
Posted on May 15, 2011, in JavaScript, Tutorial and tagged Function (mathematics), Global variable, JavaScript, Languages, Local variable, Programming, Scope (programming), scope chain. Bookmark the permalink. 5 Comments.




Pingback: Professional JavaScript, Part-5: Closures « Technical Graffiti
Pingback: Professional JavaScript, Part 2: Types and Type Conversion « Technical Graffiti
Pingback: Professional JavaScript, Part 3: Functions « Technical Graffiti
Pingback: JavaScript – A different beast « Technical Graffiti
Pingback: Professional JavaScript, Part-6: Objects without Classes « Technical Graffiti