← Human InterfacesArchive

Frontend interview prep: 10 hoisting and scope exercises (with answers)

Dec 3, 20214 min read7 reactions · 0 comments on dev.to

Originally published on dev.to. Comments and reactions live there.

Updated in 2026. The first version of this post, from 2021, said that let and const aren't hoisted. That's a very common misconception, and I believed it too. This rewrite fixes it and turns the post into exercises you can practice with.

In the variables, scope and hoisting post we covered the concepts. Now let's practice the way interviewers actually test them: "What does this code print?"

How to use this post: read each snippet, write down your answer, then open the solution. Run them in your browser console if you want to double-check. Every answer here was tested in Node.js.

Quick refresher

Declaration Hoisted? Before its line
var Yes undefined
let / const Yes, but uninitialized ReferenceError (temporal dead zone)
function declaration Yes, completely Callable
Function expression / arrow Only the variable Depends on var, let or const
class Yes, but uninitialized ReferenceError

And remember: the code doesn't move. Before running a scope, the engine registers its declarations. What differs is whether they're initialized.


Exercise 1: the warm-up

console.log(greeting);
var greeting = "Hi";
console.log(greeting);
Enter fullscreen mode Exit fullscreen mode

Solution
undefined, then "Hi".

greeting is registered before the code runs and initialized as undefined. The assignment = "Hi" happens on line 2, so the first log sees undefined.


Exercise 2: let and const

console.log(first);
console.log(second);

let first = "I'm a let";
const second = "I'm a const";
Enter fullscreen mode Exit fullscreen mode

Solution
Only one error: ReferenceError: Cannot access 'first' before initialization.

The second line never runs, because the first error stops execution. (In my original post I listed two errors. Only the first one ever appears.)

And the key point: first and second are hoisted. If they weren't, the error would be "first is not defined". "Cannot access before initialization" means the engine knows the variable exists, but it's still in the temporal dead zone.


Exercise 3: three kinds of functions

console.log(sum(2, 3));
function sum(a, b) {
  return a + b;
}

console.log(sum2(2, 3));
const sum2 = function (a, b) {
  return a + b;
};
Enter fullscreen mode Exit fullscreen mode

Solution
5, then ReferenceError: Cannot access 'sum2' before initialization.

Function declarations are hoisted with their body, so you can call them early. sum2 is just a const variable that happens to hold a function, so it follows const rules. The same applies to arrow functions.


Exercise 4: same function, but with var

sayBye();
var sayBye = function () {
  console.log("Bye");
};
Enter fullscreen mode Exit fullscreen mode

Solution
TypeError: sayBye is not a function.

Not a ReferenceError this time. With var, sayBye exists and equals undefined, and calling undefined() is a TypeError. Interviewers love this difference.


Exercise 5: the leaking block

if (true) {
  var leak = "var";
  let stay = "let";
}

console.log(leak);
console.log(stay);
Enter fullscreen mode Exit fullscreen mode

Solution
"var", then ReferenceError: stay is not defined.

var ignores block scope; it belongs to the enclosing function (or the global scope). let only exists inside the { }.


Exercise 6: shadowing with var

var x = 1;

function test() {
  console.log(x);
  var x = 2;
}

test();
Enter fullscreen mode Exit fullscreen mode

Solution
undefined.

Not 1! Inside test, there's a local var x, which is registered at the start of the function and initialized as undefined. It shadows the global x, so the log sees the local one before its assignment.


Exercise 7: shadowing with let

let x = 1;

{
  console.log(x);
  let x = 2;
}
Enter fullscreen mode Exit fullscreen mode

Solution
ReferenceError: Cannot access 'x' before initialization.

You might expect 1 from the outer scope. But the inner block has its own let x, hoisted to the top of the block and stuck in the temporal dead zone. The inner x shadows the outer one from the very first line of the block.

This is the best proof that let is hoisted.


Exercise 8: no declaration inside

var a = 1;

function outer() {
  console.log(a);
  a = 2;
}

outer();
console.log(a);
Enter fullscreen mode Exit fullscreen mode

Solution
1, then 2.

There's no var, let or const inside outer, so a refers to the outer variable through the scope chain. The function reads it and then reassigns it.


Exercise 9: same name, two declarations

console.log(typeof foo);

var foo = 1;
function foo() {}

console.log(typeof foo);
Enter fullscreen mode Exit fullscreen mode

Solution
"function", then "number".

Both declarations are registered, and the function declaration wins during hoisting. Then the line foo = 1 runs and replaces it with a number. (Please never write this in real code.)


Exercise 10: typeof and the TDZ

console.log(typeof notDeclared);
console.log(typeof inTDZ);
let inTDZ = "hello";
Enter fullscreen mode Exit fullscreen mode

Solution
"undefined", then ReferenceError: Cannot access 'inTDZ' before initialization.

typeof is usually "safe": on a variable that doesn't exist at all, it returns "undefined" instead of throwing. But a variable in the temporal dead zone is different. It exists, it's just not initialized, and typeof can't save you.



Bonus round

Two quick ones that show up in more advanced interviews:

new User();
class User {}
Enter fullscreen mode Exit fullscreen mode
function greet(a = b, b = "hi") {
  return a;
}
greet();
Enter fullscreen mode Exit fullscreen mode

Solutions
Both throw a ReferenceError.
  1. Classes are hoisted like let: they're in the temporal dead zone until their declaration.
  2. Default parameters are evaluated left to right, each in its own scope. When a tries to read b, b hasn't been initialized yet.

How did you do?

  • 10 to 12: you're ready for this part of the interview.
  • 6 to 9: review the temporal dead zone and shadowing (exercises 6, 7 and 10).
  • Under 6: go back to the concepts post and try again in a couple of days.

Which one got you? Mine was exercise 6 for a long time. Tell me yours in the comments 👇