5

I'm not really a javascript noob at all, although in my whole life I've never came across this, but am I right in assuming that javascript must assign functions before running anything or something?

In all my experience, I expected this to return 'undefined', but obviously it returns 'function'.

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

Is someone able to explain this for me?

Shannon Hochkins
  • 11,763
  • 15
  • 62
  • 95
  • possible duplicate of [Javascript function scoping and hoisting](http://stackoverflow.com/questions/7506844/javascript-function-scoping-and-hoisting) – dting Jul 10 '15 at 08:03
  • Yes. On entering an [*execution context*](http://ecma-international.org/ecma-262/6.0/index.html#sec-execution-contexts), all function and variable declarations are processed before any code is run. – RobG Jul 10 '15 at 08:10

3 Answers3

7

This behaviour of JavaScript is called hoisting. There is a good explanation on the MDN (https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)

In JavaScript, functions and variables are hoisted. Hoisting is JavaScript's behavior of moving declarations to the top of a scope (the global scope or the current function scope).

That means that you are able to use a function or a variable before it has been declared, or in other words: a function or variable can be declared after it has been used already.

Basically, if you declare a variable like this:

console.log(s);             // s === undefined
var s = 'some string';

s declaration will be "hoisted" to the beginning of the scope (i.e. there will be no ReferenceError on the line with console.log). The variable's value will not be defined at that moment though.

The same goes with assigning an anonymous function to a variable, so:

console.log(f);             // f === undefined
f();                        // TypeError: f is not a function
var f = function () {};     // assigning an anonymous function as a value
f();                        // ok, now it is a function ;)

The variable will be hoisted and thus visible in the entire scope, but it's value, even if it's a function, will still be undefined - hence the error if you try to execute it.

On the other hand if you declare a named function:

console.log(f);             // f === function f()
f();                        // we can already run it
function f() {};            // named function declaration

It's definition will also be hoisted so you can run it even in the first line of the scope you've declared it.

Community
  • 1
  • 1
Tomek Sułkowski
  • 7,081
  • 2
  • 17
  • 15
  • I really dislike the term "hoisting", it is a misnomer, and the referenced explanation is poor. It infers that the code is somehow moved, it isn't. The real answer is that function and variable declarations are *processed* before any code is executed. – RobG Jul 10 '15 at 08:15
  • Brilliantly explained, thankyou so much this clear's this up, I didn't even know that javascript did this with nested functions, I thought it was only the root scope.. Silly me – Shannon Hochkins Jul 10 '15 at 08:19
  • @RobG Yeah, fair point. It's a bit the same as what we had with "self invoking functions" for a while, isn't it? I'm also not a fan (you should hear how it's being translated to my language, it's more like "elevation" ;) ) It is quite adopted term now and I think it's easier to explain while not going into to much details (even if sacrificing the exactness a bit) – Tomek Sułkowski Jul 10 '15 at 08:22
  • @TomekSułkowski—fair enough, but inappropriate terms that are adopted as jargon or enter popular use make life more difficult (e.g. the inference of "hoisting" that code is somehow refactored). The use of "locale" instead of "language" or simply "preference" is another example. – RobG Jul 10 '15 at 08:26
0

Well in JavaScript function is nothing but Object.

When you say typeof bar(),in the bar function you are returning foo which is another function.You just returning name of the function,So,it return the constructor of the foo function.So,your typeof get the value of foo constructor which is type of function.So,it alert function.It still refer the foo because of closure

Again in the bar defination,you returning foo,but its definition is still not encountered.In JavaScript when while parsing the instruction,declaration of variable and function is placed on top in current function scope.

So, your statement

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

is equivalent to

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

    var foo = '11';

This is called JavaScript top hoist

}
RIYAJ KHAN
  • 15,032
  • 5
  • 31
  • 53
0

This is quite easily tested;

foo(1);

function foo(i) {
    if (bar()) {
        alert("foo called, bar true, i = " + i);
    };
}

foo(2);

function bar() {
    return true;
}

foo(3);

DEMO

This shows that Javascript loads all functions before executing anything. Therefor it does not matter what order functions are defined.

glend
  • 1,592
  • 1
  • 17
  • 36