Scope Chain in Javascript

JavascriptScope Chain

Javascript Problem Overview


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 :(

Javascript Solutions


Solution 1 - 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:

Solution 2 - Javascript

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:

Solution 3 - Javascript

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

Solution 4 - Javascript

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

Solution 5 - Javascript

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];

Solution 6 - Javascript

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).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTarikView Question on Stackoverflow
Solution 1 - JavascriptChristian C. SalvadóView Answer on Stackoverflow
Solution 2 - Javascriptmeder omuralievView Answer on Stackoverflow
Solution 3 - JavascriptJVMView Answer on Stackoverflow
Solution 4 - JavascriptAnatoliyView Answer on Stackoverflow
Solution 5 - JavascriptSai ChandraView Answer on Stackoverflow
Solution 6 - JavascriptWillem van der VeenView Answer on Stackoverflow