Variable and function hoisting in JavaScript

Unlike languages like C, variables and functions in JavaScript are not declared at the point of use. Instead, no matter where functions and variables are declared, they are moved to the top of their scope hoisted and assigned a default value of undefined until they're reached in code, while assignments are left in place.

What really happens, is that during compile time, the declarations are put into memory first, but physically remain in place in code. What this means is that you get access to functions and variables before they’re declared in code.

This only applies to declarations, not to expressions, and not to initializing an undeclared variable.

Example:

a = "Set the value";
console.log(a);
var a;
Code
Set the value
Output

will produce the same output as declairing it before.

var a;
a = "Set the value";
console.log(a);
Code
Set the value
Output

Variable Hoisting

When a variable declaration is encountered by the interpreter, it creates storage for that variable. This storage contains the value undefined until it is assigned in the code.

For example, the following code defines the variable after the value has already been set and accessed. However it will still function corectaly and output: Set the value

a = "Set the value";
console.log(a);
var a;
code
Set the value
Output

The keyword used when defining a variable will determine whether or not the variable is hoisted.

Variables defined with the keyword var are hoisted, and variables defined with the keyword let and const are not.

Hoisted variables

a = "Hoisted";
var a;
console.log(a);
Code
Hoisted
Output

Not Hoisted variables

a = "Not Hoisted";
let a;
console.log(a);
Code
ReferenceError: Cannot access 'a' before initialization
a = "Definition Hoisted";
let a;
console.log(a);
code
SyntaxError: Missing initializer in const declaration.
Output

Variable Hoisting Scope

When the variable is used inside a scope, the variable is hoisted only to the top of the scope. For example, the variable a defined inside this function will only be hoisted to the top of the function, resulting in a ReferenceError: a is not defined when accessed at the bottom of this script.

function functionScope() {
    a = 'Scope Hoisting';
    console.log(a);
    var a;
}

functionScope();
console.log(a);
Code
Scope Hoisting
ReferenceError: a is not defined
Output

In the above example, variable a is hoisted to the top of its scope and is only accessible inside the functionScope function.

Function Hoisting

Function hoisting works similarly to variable hoisting; this is why you can call a function in code before you declare it.

console.log(testFunction());

function testFunction(){
  return "Function output";
}
Code
Function output
Output

An error occurs if a function is used as an expression as only declarations are hoisted.

console.log(functionExpression());

let functionExpression = function(){
  return "Function output";
}
code
ReferenceError: functionExpression is not defined
output

Best Practices

Hoisting can cause undesirable and difficult-to-debug outcomes.

It is best to avoid hoisting issues and declare variables and functions first before using them. When defining variables, unless you have a specific need, it's generally better to use let than var.

You've successfully subscribed to Twisted Brackets
Great! Next, complete checkout to get full access to all premium content.
Error! Could not sign up. invalid link.
Welcome back! You've successfully signed in.
Error! Could not sign in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.