0

I have two snippets, why the first one gives a value while the second gives undefined?

Snippet 1:

function sayAlice() {
    var sayAlert = function() { alert(alice); }
    var alice = 'Hello Alice';
    return sayAlert;
}
var hi = sayAlice() ;
hi();//alert Hello Alice

Snippet 2:

alert(i); // alert undefined
var i = 1; 
Blake
  • 7,367
  • 19
  • 54
  • 80

5 Answers5

1

Your question is this:

Why sometimes defining variable after calling the variable doesn't give undefined?

Then you provide this as example:

alert(i); // alert undefined
var i = 1; 

It alerts undefined because you are issuing the alert() before i is defined.

And in the first example:

function sayAlice() {
    var sayAlert = function() { alert(alice); }
    var alice = 'Hello Alice';
    return sayAlert;
}
sayAlice()() //alert Hello Alice

The same behavior is to be expected, but it seems like your odd way of calling sayAlice happens twice with that ()(). Which basically means while it might be happening quickly, but the first call to sayAlice() will set the alice variable, but the alert is most likely happening on the second iteration called via sayAlice()().

Wait. Looking at it again, this is what is happening in the first example. This simply defines sayAlert as a function but does not actually run it:

var sayAlert = function() { alert(alice); }

But then you do this:

var alice = 'Hello Alice';

Which assigns a value to alice. And then you finally do this:

return sayAlert;

Which happens after the first two items. Meaning, at that third line you have a function defined, and then a variable defined, but it only comes together in the final line.

Which makes sense to me. But sayAlice()() with the double () seems odd.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
1

All variable declarations are moved to the top of its scope by the javascript interpreter prior to running. This means that something like this:

function sayAlice() {
    var sayAlert = function() { alert(alice); }
    var alice = 'Hello Alice';
    return sayAlert;
}
sayAlice()() //alert Hello Alice

is equivalent to:

function sayAlice() {
    var sayAlert, alice;
    sayAlert = function() { alert(alice); }
    alice = 'Hello Alice';
    return sayAlert;
}
sayAlice()() //alert Hello Alice

When you call sayAlice()() it first resolves sayAlice() which returns you the function sayAlert, binded to the variable alice which has a value of 'Hello Alice'. As long as an inner function has access to an outer variable, that variable will retain its scope. So the line after assigning sayAlert i.e. alice = 'Hello Alice' modifies the variable referenced by the sayAlert function. So then at the point of invocation you get the expected result "Hello Alice".

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
sahbeewah
  • 2,690
  • 1
  • 12
  • 18
  • “All variable declarations are moved to the top of its scope…” Interesting. Look at my answer. When `var sayAlert = function() { alert(alice); }` isn’t that just a variable being assigned a function but the function is not executed until `return sayAlert;`? – Giacomo1968 May 04 '14 at 23:34
  • 1
    I've modified my answer. The gist of it is no: the variable isn't assigned to the function. The function reads a reference to that variable which may have been changed elsewhere after the function has been declared. – sahbeewah May 04 '14 at 23:36
1

You have inside anonymous function that is a closure. Closures kinda bring their environment with them and can access local variables from it.

This MDN article describes a case very similar to yours.

Also have a look at What exactly does “closure” refer to in JavaScript? SO post.

Community
  • 1
  • 1
PM 77-1
  • 12,933
  • 21
  • 68
  • 111
1

This happens because in the second snippet, the variable 'i' is not defined in the moment of the alert is executed, but in the first snippet, what happens is that in the line

var sayAlert = function() { alert(alice); }

You are defining 'sayAlert' as a function, but this function is not executed in that moment. After that, you define the variable 'alice', and after that you return 'sayAlert', and in that moment, is when the alert is executed, and the variable 'alice' already has a value.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
Airam
  • 2,048
  • 2
  • 18
  • 36
0

Try this piece of code and you will get an entirely different result...

function sayAlice() {
    var sayAlert = function() { alert(alice); }
    return sayAlert;
    var alice = 'Hello Alice';
}

Because alice is undefined when the function is called. In your example, alice is defined.

Henry Harris
  • 161
  • 1
  • 11