user2294256
user2294256

Reputation: 1049

Why is a closure able to capture a variable declared after the closure’s definition?

function sayAlice() {
  var sayAlert = function() { console.log(alice); };
  var alice = 'Hello Alice';
  return sayAlert;
}

sayAlice()();

In console, it shows Hello Alice

Question:

var alice(variable declaration) is after var sayAlert, why it still shows the right result, not something like 'undefined'?

Upvotes: 3

Views: 97

Answers (4)

Khanh TO
Khanh TO

Reputation: 48982

It's the JavaScript Scoping and Hoisting mechanism. Look at this. Due to hoisting, javascript interprets your script like this:

<script type="text/javascript">   
   function sayAlice() {
      var alice;
      var sayAlert = function() { console.log(alice); }
      alice = 'Hello Alice';
      return sayAlert;
    }
    sayAlice()();
</script>

The var alice; is hoisted to before the declaration of var sayAlert = function() { console.log(alice); }.

Upvotes: 2

go-oleg
go-oleg

Reputation: 19480

Because at the time that sayAlert is actually executed (in the sayAlice()() call), Hello Alice has been assigned to alice. Because of closures in JavaScript, alice is available to sayAlert at execution time.

Upvotes: 2

vol7ron
vol7ron

Reputation: 42139

<script type="text/javascript">   
1:    function sayAlice() {
2:       var sayAlert = function() { console.log(alice); }
3:       var alice = 'Hello Alice';
4:       return sayAlert;
5:    }
6:    sayAlice()();
</script>
  • Line 2 is defining a function sayAlert, but not calling/executing it. If you put () after the closing brace (}), then the log would print undefined because, as you mentioned, alice isn't defined until after.

  • Line 4 just returns the sayAlert function, but again does not yet call it (notice it still doesn't have the ())

  • Line 6 receives the function previously returned from the sayAlice() call and adds () to call the returned function (sayAlert). So after Line 6 runs sayAlice, it effectively looks like sayAlert(), when it does that is when console.log(...) is called. alice is still exposed and in scope as it has not yet been destroyed by the garbage collector (similarly how closures) work.

Upvotes: 1

Edper
Edper

Reputation: 9322

Because saysAlert is a function and it is only implemented when you return saysAlert which house the function and after the fact that you declared alice.

This one will give you an undefined variable:

<script type="text/javascript">   
function sayAlice() {
var sayAlert='';
console.log(alice); // alice is undefine up to this line
var alice = 'Hello Alice';
return sayAlert;
}
sayAlice()();
</script>

Your original code:

<script type="text/javascript">   
function sayAlice() {
  var sayAlert = function() { console.log(alice); } // function sayAlert is not yet implemented
  var alice = 'Hello Alice';
  return sayAlert; // function alert is implemented after the alice variable is define
 }
 sayAlice()();
 </script>

Upvotes: 1

Related Questions