Saturday, March 16, 2013

JavaScript Scope Chain

If you are not familiar with execution context, please go through this link first -- http://softtechhelp.blogspot.in/2013/03/execution-context-in-javascript.html
Scope is collection of current Activation context and all parent execution context's Activation objects.

Here is an example -
function one() {
    var a = 1;
    two();
    function two() {
var b = 1;
        three();
        function three() {
   var c = 1;
            alert('I am at function three with-a+b+c-' + a + b + c);
        }
    }
}
one();

In the above code the execution stack will have following stack of execution contexts -
Global -> One() -> two() -> three()
So if we talk about the scope of function three() then it becomes -
[AO of three()] + [AO of two()] + [AO of one()] +[AO of Global()]

If you see we are trying to print value a,b and c from function three(), but it has only c defined in it. So in order to find the value of a and b it will traverse in "[AO of two()] + [AO of one()] +[AO of Global()]" and check if these variables are available in there.

Lexical Scope - All functions are statically bound to its parent context. Which means in the above example function three() will always be bound to two(), which in turn be bounded to one() and so on.
Example -
var myAlerts = [];
for (var i = 0; i < 5; i++) {
    myAlerts.push(
        function inner() {
            alert(i);
        }
    );
}
myAlerts[0](); // 5
myAlerts[1](); // 5
myAlerts[2](); // 5
myAlerts[3](); // 5
myAlerts[4](); // 5

In the above example function inner() was created in global context, hence it is statically bound to global. Hence once we try to print the value of i, it checks if it has "i" defined, if not then it goes to its parent context, where it finds i to be "5".

Excercise -
// a globally-scoped variable
var a = 1;

// global scope
function one() {
    alert(a);
}
one(); // 1

// local scope
function two(a) {
    alert(a);
}
two(2); //2

// local scope again
function three() {
    var a = 3;
    alert(a);
}
three(); //3

// Intermediate: no such thing as block scope in javascript
function four() {
    if (true) {
var a = 4;
    }
    alert(a); // alerts '4', not the global value of '1'
}
four(); //4

// Intermediate: object properties
function Five() {
    this.a = 5;
}
alert(new Five().a); //5

// Advanced: closure
var six = function () {
    var foo = 6;
    return function () {
// javascript "closure" means I have access to foo in here,
// because it is defined in the function in which I was defined.
alert(foo);
    }
} ();
six(); //6

// Advanced: prototype-based scope resolution
function Seven() {
    this.a = 7;
}

// [object].prototype.property loses to [object].property in the scope chain
Seven.prototype.a = -1; // won't get reached, because 'a' is set in the constructor above.
Seven.prototype.b = 8; // Will get reached, even though 'b' is NOT set in the constructor.

alert(new Seven().a); //7
alert(new Seven().b); //8      

No comments:

Post a Comment