69

I've reading scope chain in Javascript but it didn't make any sense to me, could any one tell me what is scope chain and how it works with a graphic or something even an idiot can understand. I googled it but I didn't find something comprehensible :(

6 Answers 6

74

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:

Sign up to request clarification or add additional context in comments.

12 Comments

So, currentScope 3 will override the currentScope 1 value ?
@Aaron Not override, but shadow.
@Aaron, exactly as @kangax says, within the scope of the third function the currentScope variables declared on the second, first and global scopes will be simply shadowed or hidden, their value will remain intact on the outer closures, since in the third function, you are declaring a new currentScope variable that resides in that scope, and for that when you access it there, it will be the first at the scope chain.
But what if I want to access scopeChain in the second function then will it be 3 since the place where variables defined rather than place the variables get executed ?
I think I got it, It is different than what I thought before.Let me tell you what I understood : every variables gets the value actually from where it is defined rather than executed so the functions have their own scope and e.g. currentScope 3 hides the value of currentScope 2 because they are defined in different scopes but if I want to access currentScope in the second functions it would return 2 because currentScope 3 is only effective in third function, it only effects the variables defined in its own scope. That makes sense now. So if I don't use var, then I happen to define a global one
|
21

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:

Comments

6

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();

2 Comments

Regarding -1, I want to know if my version is not at all helpful for a "idiot" to understand (as the original question states).
I don't think your comment is useless. Although it is actually the same as the very first example, but I do agree that a lot of Immediately Invoked Function Expressions in the first example could be embarrassing to Javascript beginners. However, I would make function calls in the beginning of the functions not in the end as it would make the code more readable IMHO.
6

Summary:

The scope chain is used to resolve the value of variable names in javascript. Without a scope chain the Javascript engine wouldn't know which value to pick for a certain variable name if there are multiple defined at different scopes. Scope chain in javascript is lexically defined, which means that we can see what the scope chain will be by looking at the code.

At the top of the scope chain is the global scope, which is the window object in the browser (global in NodeJS). Besides from the global scope, functions have their own scoping of variables. The scope chain can be determined by looking at where functions are defined.

When resolving a variable, inner functions first look at their own scope. If the variable cannot be found in its own scope it will climb up the scope chain and looks for the variable name in the environment where the function was defined. This look like this:

Scope chain javascript

So in our image example when innerFoo uses the variable bar it first tries to find it within the scope of the innerFoo (code within function body). Then when it doesn't find it here it climbs up the scope chain to foo. In foo there is also no variable which is named bar. Therefore, it will climb up the scope chain and now look in the global scope. In the global scope is a variable named bar with a value of 10 to which bar will be resolved.

Example:

let foo = 1;
let bar = 1;


function test (bar) {
   
   return function innerTestFunc () {
      let foo = 10;
      
      console.log(foo, bar);
    }
  
}

const innerTestFunc1 = test(5);
const innerTestFunc2 = test(20);


innerTestFunc1();  // logs 10, 5

innerTestFunc2();  // logs 10, 20

In the above example we have a function which returns a function. We first store this function in the variables innerTestFunc1 and innerTestFunc2. This creates a closure which is basically a snapshot of the scope chain of the outer environment.

Then when the functions are executed the function requires a value for both the variables foo and bar. The value of foo can be resolved at the level of the innerTestFunc and is 10 for both. 10 is already found in innerFoo, so no need to climb the scope chain for foo.

In the case of the bar variable the function cannot find it in the innerFoo. Therefore, it will climb up the scope chain. It first encounters the variable bar in the function test, therefore it will resolve value of bar to whatever the value is in the test function (5, 20 in our example).

Comments

5

This is about closure. You may use variables outer from scope in the inner scope:

function get_inner_scope () {
    var outer = 'Outer variable value';
    return function () {
        alert(outer);
    }
}
f = get_inner_scope();
f(); // alerts Outer variable value

More deatailed info with other samples by first google's link: http://blogs.msdn.com/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx

Comments

4

Scope chain in Javascript explained in layman terms

Alex is a happy guy,One fine day,walking down the road with his monthly salary in hand gets mugged.

Later he realizes that tomorrow is the last day to pay for his daughters tuition of 1000$.
He runs home,finds his savings of 400$,worries about the rest(600$).The immediate thought that flashes,is to borrow some from his father Mathew.
Mathew,the poor carpenter,devoid from any money sells his inherited bracelet for 300$ and lends it to his son Alex.
Alex having a good reputation in the society,gets the remaining 300$ from a local bank immediately and pays his daughter tuition on time.

Coming back to Scope chain in Javascript:
Alex-A function in javascript
Mathew-The immediate function,Alex is nested in.
Mathews parents-The immediate function Mathew is nested in.
Bank-Global variables.

function Bank() {
    loan=300;
    Mathew();

    function Mathew() {
        mathew=300;
        Alex();

        function Alex() {
            savings:400;
            alert('I need some money');
        }

    }

}

Bank();

Scope chain of Alex at this point looks like: [savings:400]+[mathew:300]+[loan:300];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.