I'm reading the second book of the series "You don't know JS" and I've read that functions are hoisted before variables.
So this is the code:
foo(); // 1
var foo;
function foo() {
console.log( 1 );
}
foo = function() {
console.log( 2 );
};
The output of this will be 1. But why? Functions are hoisted first and then variables. So after my function foo (the one that prints 1) is hoisted it has to be followed by the variable foo. So the result should be "undefined" instead of "1".
I expect the code to behave as if it had been:
// hoisted first
function foo() {
console.log( 1 );
}
// hoisted second
var foo; // implicitly initialized to 'undefined'
foo(); // call 'undefined' - error?
foo = function() {
console.log( 2 );
};
What's happening here?
Some ways to avoid hoisting are: Use let or const — As explained above, using let or const instead of var would throw an exception and not let the program run, hence helping catch the issue earlier. Use function expressions instead of function declarations.
Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their scope before code execution. Inevitably, this means that no matter where functions and variables are declared, they are moved to the top of their scope regardless of whether their scope is global or local.
Being able to use a variable's value in its scope before the line it is declared. ("Value hoisting") Being able to reference a variable in its scope before the line it is declared, without throwing a ReferenceError , but the value is always undefined .
Variables defined with let and const are hoisted to the top of the block, but not initialized. Meaning: The block of code is aware of the variable, but it cannot be used until it has been declared. Using a let variable before it is declared will result in a ReferenceError .
As said, functions are hoisted before variables; if the interpterer comes across var foo
after foo
has already been defined in the scope, it will simply be ignored. It doesn't assign foo
to undefined
, it only ensures that a variable named foo
exists in the current scope - which it already does.
As it says in your You Don't Know JS link:
multiple/duplicate var declarations are effectively ignored
Here's another commonly seen example of hoisted duplicate variables being ignored that might be more familiar/intuitive:
if (false)
var foo = false;
else
var foo = true;
turns into
var foo;
var foo; // does not actually do anything; does not assign `undefined` to `foo`, ignored
// foo just *happens* to not have anything assigned to it in almost all cases like this
if (false)
foo = false;
else
foo = true;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With