Skip to content

Hoisting

sergio edited this page Oct 19, 2020 · 2 revisions

Hoisting

Because the JavaScript engine reads a JavaScript file from top-to-bottom, it would make sense if we had to define a function before we invoked it:

function myFunc () {
  return 'Hello, world!';
}

myFunc();
// => "Hello, world!"
However, we can invert those two steps and everything works fine:

myFunc();

function myFunc () {
  return 'Hello, world!';
}
// => "Hello, world!"

this can happen because of the two step execution of JavaScript. The engine ignores all function invocations during the compilation phase.

// The engine ignores all function invocations during the compilation phase.
myFunc();

function myFunc () {
  return 'Hello, world!';
}
// During the execution phase, the engine invokes myFunc(), which was already initialized during the compilation phase.
myFunc();

// During the execution phase, the engine will simply ignore this function declaration that was already carried out in the compilation phase.
function myFunc () {
  return 'Hello, world!';
}

The term for this process is hoisting because it feels a bit like your declarations are being hoisted, or raised, to the top of the current scope.


Best Variable Declaration Pratices

We're going to look at some of the hoisting issues caused by var because you will encounter this weirdness in legacy code. However, the fix is straightforward: use const and let and you'll have no variable hoisting issues.

function myFunc () {
  console.log(hello);

  var hello = 'World!';
}
// => undefined

myFunc();
// LOG: undefined
// => undefined

In JavaScript, hoisting only applies to variable declarations; not variable assignments. As a quick refresher on that terminology:

// Declaration:
let hello;

// Assignment:
hello = 'World!';

// Declaration and assignment on the same line:
let goodnight = 'Moon';
  • During the compilation phase, the JavaScript engine initializes the variable hello, storing it in memory.

  • At this point, however, no value is assigned to the variable.

  • As far as the JavaScript engine is concerned, the variable hello exists, but it contains undefined.

  • The variable will contain undefined until it's assigned a different value during the execution phase.

so this sample code:

function myFunc () {
  console.log(hello);

  var hello = 'World!';
}

actually behaves has this rearranged sample code:

function myFunc () {
  var hello;

  console.log(hello);

  hello = 'World!';
}

Only after the logging event the varaible is assigned with the value of 'World!'.

myFunc();
// LOG: undefined
// => "World!"

so the juice is that during compilation the variable get identified but remain undefined.


Precaution to Avoid Hoisting Problems

If, for whatever reason, your current project requires that you use var, follow our rule for function declarations and declare everything at the top of its scope

// BAD
function myBadFunc () {
  console.log('Just doing some other stuff before we get around to variable declarations.');

  var myVar = 42;
}

// GOOD
function myGoodFunc () {
  var myVar = 42;

  console.log("Much better! The variable declaration is at the top of the scope created by 'myGoodFunc()', so there's no chance it gets 'hoisted'.");
}

The most important thing to keep in mind is: don't use var. Variables declared with const and let do technically get 'hoisted', but the JavaScript engine doesn't allow them to be referenced before they've been initialized.

  • Declare all of your functions at the top of their scope. If the functions are declared in the global scope, simply put them at the top of the JavaScript file. If they're declared inside another function, put the declaration at the top of the function body.

  • Make your default variable declaration keywords const and let. You might occasionally find old code or see code samples that has var. Don't panic! Be aware that var-declared variables are not scoped like let and might require a bit of careful inspection if you're debugging some code with them.

Clone this wiki locally