Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unexpected results with function and variable hoisting [duplicate]

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?

like image 890
BoSsYyY Avatar asked May 26 '18 07:05

BoSsYyY


People also ask

How do you avoid variable hoisting?

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.

WHAT IS function and variable hoisting?

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.

What does it mean for a variable to be hoisted?

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 .

Is hoisting possible with Let variable?

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 .


1 Answers

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;
like image 148
CertainPerformance Avatar answered Sep 22 '22 18:09

CertainPerformance