Imagine a teacher who quickly checks the attendance list before class starts. The teacher notes who is present, then the class begins. JavaScript does something similar: before it runs your code it makes a short pass to note declarations. This behaviour is called hoisting.
Hoisting explains many surprises beginners see β like why var sometimes gives undefined, or why calling a function works even if the function appears later in the file. In this post we will explain hoisting in simple words, show clear code examples, and give short tips you can use right away.
π Why hoisting matters
When JavaScript runs a script it does two small steps for each scope (global or function):
- Creation step β it looks for declarations and prepares memory.
- Execution step β it runs the code line by line.
Hoisting happens because of that first step. If you know these two steps, many confusing behaviours become easy to understand.
β Easy intuition (no hard words)
- During the creation step,
varnames are set up and given the valueundefined. -
letandconstnames are known but not ready to use until the code reaches them β this waiting period is called the Temporal Dead Zone (TDZ). - Function declarations are ready in creation step with their full body, so you can call them even before the line where they are written.
π§ͺ Short examples (see it clearly)
1) var example β gives undefined
console.log(a); // undefined
var a = 5;
console.log(a); // 5
What happened: JavaScript set up a at the start (with value undefined), then later the assignment a = 5 happened.
2) let / const β not ready before their line
console.log(b); // ReferenceError
let b = 10;
What happened: b is known to the engine, but it is not usable until the line let b = 10 runs. Accessing it early gives an error.
3) Function declaration β can be called early
greet(); // works: "Hello!"
function greet() {
console.log("Hello!");
}
What happened: The whole greet function is set up during the creation step, so it is ready to call even before the code reaches its line.
4) Function expression β not hoisted the same way
sayHi(); // TypeError: sayHi is not a function
var sayHi = function() {
console.log("Hi");
};
What happened: sayHi was set up as undefined at creation. The function value is only assigned later. So calling it too early causes an error.
π Simple step-by-step of what engine does
-
Creation step: JavaScript finds declarations.
-
varβ create name, set toundefined. -
let/constβ reserve name, do not set a value yet (TDZ). - Function declarations β create name and set function value.
-
- Execution step: JavaScript runs the code line by line, doing assignments and calls.
This model is enough to reason about most hoisting cases.
β οΈ Common beginner mistakes (and quick fixes)
- Thinking hoisting moves code. It does not rewrite your source β it just prepares memory first. Fix: Read code top to bottom, initialise variables where you use them.
-
Using
vareverywhere.varcan causeundefinedsurprises. Fix: Useconstby default,letwhen you must reassign. - Expecting function expressions to be callable early. Only function declarations are available before execution reaches them. Fix: Use function declarations when you need that behaviour, otherwise keep functions close to where they are used.
π Practical rules you can start using
- Prefer
constfor values that do not change,letfor values you will change. Avoidvar. - Initialise variables near where you use them β it is clearer for readers and for you.
- If you need a helper that should be available anywhere in the scope, a function declaration is OK. Otherwise use function expressions for clearer order.
π― Bonus: How to explain hoisting in an interview (short and clear)
30-second answer:
Hoisting is the JS engineβs creation step that runs before code execution.
varis hoisted and set toundefined.letandconstare known but not usable until their line (TDZ). Function declarations are hoisted with their body.
Show quickly: paste this in the interview:
console.log(x); // undefined
var x = 1;
console.log(y); // ReferenceError
let y = 2;
foo(); // works
function foo() { console.log('hi') }
bar(); // TypeError
var bar = function() { console.log('ho') }
Common follow-ups: TDZ meaning, leading practice (const/let), and difference between function declarations and expressions.
π§ Key takeaways
- Hoisting = creation step + execution step.
-
varβ hoisted and initialised asundefined. -
let/constβ hoisted but not initialised (TDZ) until the line runs. - Function declarations β hoisted with the function body.
- Prefer
const/letand keep declarations clear and close to use.
π About Me
Hi, I'm Saurav Kumar β a Software Engineer building web and mobile apps using JavaScript, TypeScript, React, Next.js, and React Native.
I explore using AI tools to speed up development and I share beginner-friendly tutorials and practical tips.
π Connect with me:
If this helped you, please share with a friend learning JavaScript.
Until next time, keep coding and keep learning π
Top comments (0)