← Back to list

JavaScript: setTimeout, setInterval, Closures & the Event Loop — Interview Questions with Code…

During frontend and full-stack interviews, questions around setTimeout, setInterval, closures, and the event loop are extremely common…

Ritambrayadav · 2026-01-05 10:11 · 0 claps · 3.8 min read
#frontend-development #fullstack-development #mern-stack-development #javascript-setinterval #settimeout
Open on Medium ↗
Wiki topics: 🌐 · Web Development

JavaScript: setTimeout, setInterval, Closures & the Event Loop — Interview Questions with Code snippet (Exp: 2–5 yrs)

During frontend and full-stack interviews, questions around setTimeout, setInterval, closures, and the event loop are extremely common. Most of them look simple but are designed to test your deep understanding of JavaScript execution.

This article covers real interview questions that I faced during my interviews in 2025–2026 with explanations.

  1. Output-Based Question: Classic Closure Issue
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
//output
3
3
3

Why?

  • var is function-scoped, not block-scoped.
  • The loop finishes immediately.
  • By the time setTimeout callbacks execute, i has become 3.
  • All callbacks reference the same i.

This is a closure over a shared variable, not a copy.

2. Fixing the Closure Issue Using let

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
// utput
0
1
2

Why?

  • let is block-scoped.
  • Each iteration creates a new binding of i.
  • Each timeout callback closes over its own i.

3. Fixing the Closure Issue Using IIFE

for (var i = 0; i < 3; i++) {
  (function (i) {
    setTimeout(() => console.log(i), 1000);
  })(i);
}

Why does this work?

  • IIFE creates a new function scope
  • The current value of i is passed as an argument
  • Each callback gets its own copy

Alternative: Passing Arguments to setTimeout

for (var i = 1; i <= 3; i++) {
  setTimeout((num) => console.log("Arg:", num), 1000, i);
}

4. Chained setTimeout for Sequential Logs

for (let i = 1; i <= 5; i++) {
  setTimeout(() => console.log(i), i * 1000);
}
// Soltion
1 (after 1s)
2 (after 2s)
3 (after 3s)
4 (after 4s)
5 (after 5s)

Each timeout is scheduled with a different delay.

5. Recursive setTimeout for Controlled Intervals

function repeatLog(i) {
  if (i > 5) return;
  console.log(i);
  setTimeout(() => repeatLog(i + 1), 1000);
}
repeatLog(1);

How is this different from setInterval? setTimeout (recursive):

  1. Next call waits for the previous execution to finish
  2. Better for long tasks
  3. More control

setInterval:

  1. Fires on a fixed schedule.
  2. Can overlap if the task is slow.
  3. Less control. ✅ Recursive setTimeout is safer in production code.

If the callback takes too long (e.g., heavy computation or blocking code), the next tick doesn’t wait — it still fires on schedule.

6. Cancelling setTimeout

const id = setTimeout(() => console.log('Executed'), 2000);
clearTimeout(id);

The callback will never execute.

7. Cancelling setInterval

let count = 0;
const id = setInterval(() => {
  console.log(count++);
  if (count > 3) clearInterval(id);
}, 1000);

// solution
0
1
2
3

Stops when count > 3.

8. setTimeout with Delay = 0

console.log('Start');
setTimeout(() => console.log('Inside Timeout'), 0);
console.log('End');
// solution
Start
End
Inside Timeout

Why?

  • setTimeout goes to the macrotask queue
  • Executes only after:
  1. Call stack is empty.
  2. Microtasks are done

9. Nested setTimeout

setTimeout(() => {
  console.log('First');
  setTimeout(() => {
    console.log('Second');
  }, 0);
}, 0);

//output
First
Second

Why?

  • First timeout executes
  • The second timeout is scheduled after the first callback finishes
  • Each setTimeout creates a new macrotask

10. Countdown Using setInterval

let counter = 5;
const id = setInterval(() => {
  console.log(counter--);
  if (counter < 0) clearInterval(id);
}, 1000);
//Output
5
4
3
2
1
0

Stops when counter becomes -1.

  1. setTimeout Inside a Loop with Different Delays
for (let i = 1; i <= 3; i++) {
  setTimeout(() => {
    console.log(`Delayed by ${i} second(s)`);
  }, i * 1000);
}

What does this do?

  • Logs messages after 1s, 2s, and 3s
  • Common interview test for understanding timer scheduling

12. Debouncing with setTimeout

let timer;
function debounceFn() {
  clearTimeout(timer);
  timer = setTimeout(() => {
    console.log('Debounced!');
  }, 300);
}

What happens?

Calling debounceFn() multiple times quickly:

  • Cancels previous timeout.
  • Only the last call executes.

Used in:

  • Search inputs
  • Resize events
  • Auto-save

13. Throttling with setTimeout

let throttlePause;
function throttleFn() {
  if (throttlePause) return;
  throttlePause = true;
  setTimeout(() => {
    console.log('Throttled!');
    throttlePause = false;
  }, 1000);
}

What does this do?

  • Ensures the function runs at most once per interval
  • Ignores calls during the pause window

Used in:

  • Scroll events
  • Button spam prevention

14. Delayed Execution Without setInterval (Closures)

function delayedLogger(n) {
  for (let i = 1; i <= n; i++) {
    (function (i) {
      setTimeout(() => console.log(i), i * 1000);
    })(i);
  }
}
delayedLogger(3);

How does this mimic setInterval?

  • Each timeout fires one after another
  • Uses closures + increasing delay
  • No shared state or interval drift

15. setTimeout Inside async Function (Event Loop Test)

async function demo() {
  console.log('1');
  setTimeout(() => console.log('2'), 0);
  await Promise.resolve();
  console.log('3');
}
demo();
console.log('4');

// output
1
4
3
2

Event Loop Explanation

  1. 1 → synchronous
  2. setTimeout → macrotask queue
  3. await Promise.resolve() → microtask
  4. 4 → synchronous
  5. Microtasks run → 3
  6. Macrotasks run → 2
  7. ❓ Predict the output and explain event loop behavior: setTimeout(() => console.log(‘2’), 0) is scheduled: Placed in the macrotask queue (to run after the current call stack and microtasks)await Promise.resolve(): It pauses the function at this point.The continuation (console.log(‘3’)) becomes a microtask.

Final Thoughts

These questions are not about syntax — they test:

  • Closures
  • Scopes
  • Event loop
  • Microtasks vs macrotasks
  • Real-world async behavior

If you understand why these outputs happen, you’re already ahead of most candidates. If you have any queries, suggestions, or find any mistakes, please do let me know via the comment section, or find my contact details on my profile.

In 2026, if you are planning for Frontend, Backend, Fullstack, and MERN stack interviews, do visit all the articles on my profile. All the JS, HTML, CSS, React, and Node interview questions are covered from my interview experiences from Top indian companies and MNCs.

Be interview-ready in 2026


메타데이터
post_id
c7c7afee7d1e
slug
javascript-settimeout-setinterval-closures-the-event-loop-interview-questions-with-code-c7c7afee7d1e
url
https://medium.com/@ritambrayadav20/javascript-settimeout-setinterval-closures-the-event-loop-interview-questions-with-code-c7c7afee7d1e
canonical_url
https://medium.com/@ritambrayadav20/javascript-settimeout-setinterval-closures-the-event-loop-interview-questions-with-code-c7c7afee7d1e
author_url
https://medium.com/@ritambrayadav20
status
ok
fetched_at
2026-08-23 18:15:22