Quiz

How can you avoid problems related to hoisting?

Topics
JavaScript

TL;DR

Use const by default and let when reassignment is required, keep declarations close to their first use, and never read a binding before it is initialized. let and const are still hoisted—their bindings exist from the start of the block—but they remain in the temporal dead zone until evaluation reaches the declaration. Static-analysis rules such as no-use-before-define and no-undef catch the risky patterns.

// Use let or const
let x = 10;
const y = 20;
console.log(x, y); // Output: 10 20
// Declare functions before calling them
function myFunction() {
console.log('Hello, world!');
}
myFunction(); // Output: 'Hello, world!'

How can you avoid problems related to hoisting?

Understand hoisting

“Hoisting” describes the observable result of JavaScript creating bindings while it instantiates a scope before evaluating its statements. The engine does not physically move source code.

Use let and const instead of var

let and const are block-scoped. Their bindings are hoisted to the start of the block but stay uninitialized in the temporal dead zone, so an early access throws instead of silently producing undefined.

console.log(x); // undefined. (Binding initialized before statements run)
console.log(y); // ReferenceError: Cannot access 'y' before initialization. (TDZ)
console.log(z); // ReferenceError: Cannot access 'z' before initialization. (TDZ)
// Avoid using var
var x = 10; // Function- or script-scoped; assignment happens here
// Use let or const
let y = 20; // Block-scoped; initialized here
const z = 30; // Block-scoped; initialized here

Keep declarations close to their first use

Declare and initialize a binding before its first use, preferably close to the code that needs it. Moving every declaration to the top can widen its apparent lifetime and separate it from its purpose.

function example() {
let a = 1;
const b = 2;
// Now use a and b
console.log(a + b);
}
example(); // Output: 3

Declare functions before calling them

Function declarations are initialized during scope setup; function expressions are evaluated in place. Keeping either form before its first call usually makes control flow easier to read, even when an earlier call to a declaration would be valid.

// Function declaration (hoisted)
function myFunction() {
console.log('Hello, world!');
}
myFunction(); // No issues here
// Function expression (created when this declaration is evaluated)
const anotherFunction = function () {
console.log('Hello again!');
};
anotherFunction(); // No issues here

Avoid using undeclared variables

Using undeclared variables can lead to unexpected behavior due to hoisting. Always declare your variables before using them.

// Avoid this
function badExample() {
x = 10; // ReferenceError in strict mode
console.log(x);
}
// Do this instead
function goodExample() {
let x = 10; // x is declared
console.log(x);
}
goodExample();
badExample();

Further reading

Exercícios

Verifique seu entendimento
Beta
Verifique seu entendimento Exercício
Verifique seu entendimento Exercício

Which practices reduce bugs related to declaration timing and early access? Select all that apply.