2

I am going through book "Java Script Ninja" and there is chapter on closures and scope.

There is code example:

var innerHolder;
function outerFunction() {
    console.log("outerFunction: "+x);

    function innerFunction() {
        console.log("innerFunction: "+x);
    }
    innerHolder = innerFunction;
}


console.log("outerScope "+x);
var x = 15
outerFunction();
innerHolder();

Result of this is:

outerScope undefined

outerFunction: 15

innerFunction: 15

Then the book says:

  1. All variables in an outer scope, even those declared after the function declaration, are included.

  2. Within the same scope, variables not yet defined cannot be forward-referenced.

I do understand the second point, but the first point is not entirely clear to me. It appears as this is true but only if the variable is actually declared before function call is made. In my logic because variables are not hoisted if variable is declared after call to inner function, it is not in the outer scope at the time and therefore it will not be picked by closure. Is that correct?

I.e. If I modify the code:

console.log("outerScope "+x);
outerFunction();
innerHolder();
var x = 15

The result will be:

outerScope undefined

outerFunction: undefined

innerFunction: undefined

Taks
  • 2,033
  • 4
  • 18
  • 23

1 Answers1

1

First all the function declarations will be processed by Javascript. Then everything will be just processed from left to right.

function sayHi(){console.log(x)}; sayHi(); var x = 1; // undefined
function sayHi(){z()}; sayHi(); function z() {console.log(2)}; var x = 1; // 2

So you're right. What he wants to show you is the nature of the lexical scope see the included link and you'll get much better understanding of that than from the example included in that book.

This is the order in which everything will be executed in your example:

   var innerHolder;// 2 (innerHolder = undefined)
   function outerFunction() { // 1
        console.log("outerFunction: "+x) // 6;

        function innerFunction() { // 7
            console.log("innerFunction: "+x) // 10;
        }
        innerHolder = innerFunction; // 8
    }


    console.log("outerScope "+x); // 3
    var x = 15 // 4
    outerFunction(); //5
    innerHolder(); // 9
Community
  • 1
  • 1
sudo
  • 343
  • 1
  • 11
  • I understand second example the z() is hoisted. What I don't understand is why variable is picked from outter scope if its declared before call to inner function. I.e.: function sayHi() { console.log(x) } var x = 15; sayHi(); I believe lexical scope is the answer? I will have a look – Taks Apr 05 '15 at 11:36
  • Javascript will try to find that variable in the scope of the function, but if it doesn't find it, it will try to find it in the global scope. That's why for better performance you want to prevent Javascript from looking all the way down the tree and declare variables locally. – sudo Apr 05 '15 at 11:41
  • Interesting point with lexical scopes. My question was more about: When does something appear in closure scope. With focus on outer scope for closure. So variable from outter scope will only appear for closure if its declared before call to the function that has the closure. – Taks Apr 05 '15 at 11:42
  • 1
    Everything which doesn't have the scope defined explicitly will belong to the global scope. Things don't appear in the closure scope, but are accessible from within the closure, the function is so to say borrowing the global scope in your example that's what the designers of Javascript told it to do. Please note that there many ways to build a programming language, as long as the different parts of the language doesn't contradict with themselves it's all just personal preference (the Javascript language doesn't contradict itself, luckily). – sudo Apr 05 '15 at 11:47
  • But its borrowing the global scope as it is in time of the function execution right? So if variable is declared after execution, it will not be visible for that function at the time. – Taks Apr 05 '15 at 11:49
  • 1
    That's right, but in your example things go this way: 1. Function declaration; 2. Variable declaration; 3. Function execution; – sudo Apr 05 '15 at 11:51
  • See the edit. First all the function declarations will be processed, then Javascript will process everything from left to right. – sudo Apr 05 '15 at 11:57