9

    function bar() {
        return foo;
        foo = 10;
        function foo() {}
        var foo = 11;
    }
    console.log(typeof bar());

typeof bar returns function?! why not number?

2
  • 1
    That code is a mess... I have no idea what are you trying to achiev. The reason why it returns function is, because you are returning empty foo() function without any return value. Algorithms work consecutively, but functions are not declared consecutively. Commented Feb 24, 2017 at 7:02
  • 3
    remember 1 rule, js compiler move the function declaration in a context at the top. this key will resolve all your query Commented Feb 24, 2017 at 7:13

6 Answers 6

4

JS functions are executed in two passes three passes. First, the engine walks through the code, looks for function declarations and hoists them (=moves them to the top), second, it hoists variable declarations (unless the same name is already hoisted), finally it runs the "normalized" code.

In your snippet, the engine picks function foo and moves it to the top of the function. The subsequent var foo is ignored.

This results in the following "normalized" code:

function bar() {
    function foo() {} 
    return foo;
    foo = 10;
    foo = 11;
}

which explains your results.

Reference: Declaration Binding Instantiation, notice steps 5 and 8.

Sign up to request clarification or add additional context in comments.

9 Comments

Why does function bar() { return foo; foo = 10; foo = function foo() {} var foo = 11; } console.log(typeof bar()); log undefined?
@guest271314: thanks, I added the word "declarations": function declarations are hoisted first. Yours is a definition, which is just an ordinary value.
can't decide whether foo is global or local, if it's not local then it makes it global??
@p0k8_: no, there are three states at the parsing time: global, local and "don't know yet".
function bar() { return foo; foo = 10; function foo() {} },,, so hoisting only comes with variables not with function,,,, as we can call function first and below in we can define
|
3

return foo just references to function foo() {} so it's returning Function

function bar() {
    return foo; // function foo() {} 
    foo = 10; 
    function foo() {}
    var foo = 11;
}
alert(typeof bar()); // function

another scenario

function bar() {
    return foo;  // returns foo undefined as no value is assigned       
    foo = 10;           
    var foo = function () {}   // referenced to variable
    var foo = 11;       
}

alert(typeof bar()) // undefined 

here it will return number

function bar() {
    foo = 10; 
    return foo; // 10
    function foo() {}
    var foo = 11;
}
alert(typeof bar()); // number 10

this too will return a closure function which returns a number

function bar() {
    foo = 10;
    return function () {
      return foo 
    }
    var foo = 11;
}
alert(typeof bar()()); // number 10

Comments

2

You messed with return :).

It is not about the priority. It is about the thing you last return from the function. Alter them and see. You get number.

function bar() {

    function foo() {}
    var foo = 11;
        return foo;
    foo = 10;
}
alert(typeof bar());

This gives you number.

1 Comment

To expand upon this, I think you are also running afoul of some hoisting that is complicating matters...
1

The reason for this behavior is due to Hoisting in javascript.

When javascript is interpreted, any variable definition is processed first, so in the scope of your function, the actual order of the call is something like this:

function bar {
    var foo = 11;
    function foo() {}
    return foo;
}

The hoisting positions the var foo = 11 declaration first, and then the foo is overwritten by the foo named function. hence return foo returns the function itself, not the numeric value.

This is a good starting point to understand hoisting

4 Comments

I think you're mostly correct, but the variable declaration gets hoisted, but not the assignment. That's the real reason that the typeof function is winning out.
I don't think this is correct, var foo isn't handled at all.
Okay, I see... but do you think it should be: var foo; function foo() {} return foo; foo = 11;
@WeijingLin no, it depends on what you want to achieve, in general the code from that example is very unorganised, and has no evident purpose, it seems to be merely an example to showcase hoisting in JavaScript. What exactly do you aim to achieve?
1

The return statement prevents the number assignments from executing, but the function declaration doesn't care.

function bar() {
   return foo;
   foo = 10;          //assignment is never executed
   function foo() {}  //function definition happens even if code is not executed
   var foo = 11;      //assignment is never executed
   }
console.log(typeof bar());

To test this out, comment out the function foo() {} line. You'll see that bar() returns undefined. The assignment statements define foo even if the statements are not executed, but they don't clobber the value of foo until they are executed (thus leaving the function definition in place).

Fiddle with the code:
https://jsfiddle.net/vwm31faq

Comments

0

Function gets Hoisted to the top of the current scope, hence you code at execution time would look like

function bar() {
    var foo;
    function foo() {}
    return foo;
    foo = 10;
    function foo() {}
    foo = 11;
}
console.log(typeof bar());

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.