tl; dr If you don't name anything until everything boots up, you should be fine.
Change: A review that also covers some ES6 declarations ( let , const ): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
This strange behavior depends on
- How do you define functions and
- When you name them.
Here are some examples.
bar();
bar(); function bar() { foo();
bar(); function bar() { foo();
function bar() { foo();
This is because of something called a climb !
There are two ways to define functions: Declaring a function and expressing a function. The difference is annoying and the minute, so let's just say this slightly wrong thing: if you write it as function name() {} , this is an announcement , and when you write it as var name = function() {} (or an anonymous function assigned to return , such things), this is an expression of a function.
First, let's see how variables are processed:
var foo = 42;
Now, how function declarations are processed:
var foo = 42; function bar() {}
The var statements throw the foo creation to the very top, but have not yet assigned a value to it. The function declaration is as follows, and finally, the value is assigned to foo .
What about this one?
bar(); var foo = 42; function bar() {}
Only the declaration foo moves to the top. Assignment occurs only after a call is made to bar , where it was before all lifts occurred.
And finally, for brevity:
bar(); function bar() {}
Now, what about functional expressions?
var foo = function() {} foo();
Like ordinary variables, the first foo declared at the highest point in the region, then it is assigned a value.
Let's see why the second example causes an error.
bar(); function bar() { foo(); } var foo = function() {}
As we saw earlier, only the creation of foo raised, the assignment occurs where it appeared in the "original" (un-raised) code. When bar is called, a value is assigned before foo , so foo === undefined . Now in the functional body of bar , as if you are doing undefined() , which causes an error.