2

Can someone please explain to me what is happening in following three examples? My thoughts are for the first example, bar is not executed (it's just a function declaration) so when foo is executed, the output is undefined? For the second example, bar is executed so that value 3 is returned. For the third example I don't have a clue why it produces 8.

// 1)
function foo() {
    function bar() {
        return 3;
    }
}
foo(); // undefined

// 2) 
function foo() {
    function bar() {
        return 3;
    }
    return bar();
}
foo(); // 3

// 3)
function foo(){ 
    function bar(){
        return 3;
    }
    return bar();
    function bar() { 
         return 8;
    }
 }
 foo(); // 8
Flip
  • 6,233
  • 7
  • 46
  • 75
DaeYoung
  • 1,161
  • 6
  • 27
  • 59
  • `bar()` is declared twice in the third example. Since the second one is declared last, it returns 8. – ElGavilan May 06 '15 at 19:23
  • 1) In 1st case, if you call foo(), foo() is executed and bar() is available now. But inorder to execute the bar you need to call it explicitly. 2) in second case, You are calling foo(), and in foo() bar is available, and you are calling bar() by writing return bar(); 3) In third case, see the explanation in second case. For extra info see this: http://stackoverflow.com/questions/7295634/javascript-nested-function – The Guest May 06 '15 at 19:25
  • how to call bar explicitly? – DaeYoung May 06 '15 at 19:27
  • 1
    @DaeYoung `return bar();` – ElGavilan May 06 '15 at 19:27
  • @DaeYoung I mean, in first case, when you call foo(), bar() is available, but you are not calling the bar() function though it is availabale. – The Guest May 06 '15 at 19:28

6 Answers6

3

You're correct about examples 1 and 2, so I'll just address example 3.

While it looks like you're calling bar() before you redefine it, function declarations are treated specially. The functions are all defined when the containing scope is first entered, they're not executed in order. If you have multiple declarations for the same function, the last one is the effective one. So there's no difference between:

function bar() {
    // version 1
}
return bar();
function bar() {
    // version 2
}

and:

function bar() {
    // version 2
}
return bar();

This is the way that a function declaration differs from assigning a function expression to a variable. Had you instead written:

function foo() {
    var bar = function() {
        return 3;
    }
    return bar();
    var bar = function() {
        return 8;
    }
}
foo();

then it would have returned 3.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • This is IMO the best answer because it mentions the var x = function syntax and when function declarations are executed. – Patrick White May 06 '15 at 19:33
2

The real answer you're looking for is hoisting.

In your third example, what is really executed by the Javascript interpreter is:

var foo = function() { 
  var bar = function() {
    return 3;
  }
  var bar = function() { 
    return 8;
  }
  return bar();
}

foo(); // 8

The function declarations are processed first, on the scope of the function from which they have been called. I highly recommend you find more lecture about what hoisting is in Javascript, for instance you can start with this:

http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

floribon
  • 19,175
  • 5
  • 54
  • 66
0

Your assumptions on the first two examples are correct.

The last example returns 8 because bar is being redefined before foo is called. Here's a basic timeline of events:

  1. foo is defined

    • bar is defined as a function that returns 3
    • bar is redefined as a function that returns 8
  2. foo is invoked
    • the return statement is hit and the redefined bar function is executed, returning 8
Sumner Evans
  • 8,951
  • 5
  • 30
  • 47
0

In your third example, bar() is declared twice. The declaration that returns 8 is declared last, so it redefines bar() and is the declaration that is executed.

function foo(){ 
    function bar(){ // first declaration of bar()
        return 3;
    }

    return bar(); // this executes the code in bar() as it was most recently redefined

    function bar() { // second and last declaration of bar(); this redefines the
                     // first declaration
         return 8;
    }
 }
 foo(); // 8
ElGavilan
  • 6,610
  • 16
  • 27
  • 36
0

If a function with the same name and scope is declared twice, it will ignore the first and execute the second function. That is what is occurring is #3.

Ben Rondeau
  • 2,983
  • 1
  • 15
  • 21
  • so return bar() is called after function bar(){ return 8; } declaration? – DaeYoung May 06 '15 at 19:28
  • @DaeYoung Youe `return bar()` statement is what calls the method declared as `function bar(){ return 8; }` – ElGavilan May 06 '15 at 19:29
  • When javascript is executed, hoisting will occur for the `var bar = function()`. This means it will be brought to the top of the scope since it is a variable declaration, and then functions which use/manipulate that data will be run (in this case, the `return` statement). Google javascript hoisting for more on that topic – Ben Rondeau May 06 '15 at 19:31
0

When the following is executed both function declarations are hoisted to the top of the IIFE scope - the second declaration overriding the first.

(function IIFE(){ 
    function bar(){
        return 3;
    }
    return bar();
    function bar() { 
         return 8;
    }
})()

(function IIFE(){ 
    function bar(){
        return 3;
    }
    function bar() { 
         return 8;
    }
    return bar();
})()

(function IIFE(){ 
    function bar() { 
         return 8;
    }
    return bar();
})()