2

I try to figure out, how closure works, this is my example

function func1(func) {
    return function(summand) {
        return func() + summand;
    }
}

var func2 = function() {
    return 3;
}

var func3 = func1(func2);
var value = func3(4);

alert(value);

var func2 = function() {
    return 100;
}

var newValue = func3(100);
alert(newValue);

First of all let breaks down the code. I write a function that expected as parameter a function and it will return a function.

function func1(func) {
    return function(summand) {
        return func() + summand;
    }
}

Then i defined the parameter function func2 in expression form

var func2 = function() {
    return 3;
}

then call func1 and give func2 as pamerater. As result i have got a function back

var func3 = func1(func2);

then i execute function and pass 4 as parameter argument

var value = func3(4);

as result i've got 7. Then i overwrite func2 and return 100

var func2 = function() {
    return 100;
}

then call func3 again and pass as parameter value 100.

var newValue = func3(100);

as result i've got 103. The first function that i defined(that return a function and takes function as parameter), will still used the first version of func2. This the power of closure, i know it.
But look at the following code, when i define func2 as function declaration not as expression, then func2 will overwrite

function func1(func) {
    return function(summand) {
        return func() + summand;
    }
}

function func2() {
    return 3;
}

var func3 = func1(func2);
var value = func3(4);

alert(value);

function func2() {
    return 100;
}

var newValue = func3(100);
alert(newValue);

The first value is 104 and second is 200.
My question is, why when i use function declaration it will overwrite the old function, in this example is func2. But when i use function expression it will keep the reference to old func2.
It that because of function hoisting?

softshipper
  • 32,463
  • 51
  • 192
  • 400
  • Related: [var functionName = function() {} vs function functionName() {}](http://stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname) – Jonathan Lonowski Nov 28 '13 at 16:37

3 Answers3

4

This is not because of closures.

Just like you figured out - this issue is because of function hoisting.

You can think of function declarations as "moved up" to the start of the current scope.

var f2 = function(){
    return 50;
}
function f2(){
    return 100;
}

In this case, f2 is 50 because it gets parsed in a way that's similar to:

var f2 = function(){
    return 100;
}
var f2 = function(){
    return 50;
}

Because of hoisting.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
3

It is because of hoisting. Using the function statement rather than the function expression causes the function func2 to get hoisted to the top of the scope. You are overwriting func2 before any code in the scope gets executed.

because of hoisting you code actually looks like this:

function func1(func) {
    return function(summand) {
        return func() + summand;
    }
}

function func2() {
    return 3;
}

// Hoisted!!! Overwriting the previous func2 definition.
function func2() {
    return 100;
}

var func3 = func1(func2);
var value = func3(4);

alert(value);

var newValue = func3(100);
alert(newValue);

Inside func1, func is a stable reference to the function that it was passed... It's just that you are passing the return 100; version before you think you are.

J. Holmes
  • 18,466
  • 5
  • 47
  • 52
1

When you use the function foo() { ... } style, you are defining a function with the name foo. When you use the var foo = function() { ... } style, you are declaring a variable foo (which will be hoisted), and assigning it the anonymous function as its value.

It is ok to write

var a;
a = 2;
// ...stuff...
a = 3;

and we expect the value to be 3. So it is here, hoisting makes this like:

var func2;
func2 = function() { .. some stuff.. };
// ...stuff...
func2 = function() { .. some other stuff .. };

By comparison, I think if you define the functions, it will just take the one or other function definition in the initial parse.

Phil H
  • 19,928
  • 7
  • 68
  • 105