đź§  Top 10 JavaScript Interview Questions (With Detailed Answers for Intermediate Front-End Developers in 2025)

Whether you’re prepping for your next front-end interview or brushing up your JavaScript fundamentals, it’s crucial to understand how the language works beyond just syntax.

In this post, we’ll walk through 10 frequently asked JavaScript questions, often encountered at the intermediate level. Each question includes practical examples and explanations to help you feel confident in any interview scenario.

1. What’s the difference between var, let, and const?

Understanding variable declarations in JavaScript is fundamental:

KeywordScopeHoistingReassignableRedeclarable
varFunctionYes (initialized as undefined)âś… Yesâś… Yes
letBlockYes (but not initialized)✅ Yes❌ No
constBlockYes (but not initialized)❌ No❌ No
function test() {
  console.log(a); // undefined due to hoisting
  var a = 10;

  // console.log(b); // ReferenceError: Cannot access 'b' before initialization
  let b = 20;
  const c = 30;
}

2. What Is a Closure?

A closure is when a function “remembers” its outer lexical environment even after the outer function has finished executing.

Example: SetTimeout in Loops

⏱ Closure captures the current value of i before it changes in the next iteration.

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

// Output after 1s: 1
// Output after 2s: 2
// Output after 3s: 3
Example 2: Memoization (Performance Optimization)

Closures help cache expensive function results.

function memoizedAdd() {
  const cache = {};

  return function(num) {
    if (cache[num]) {
      console.log('From cache');
      return cache[num];
    }
    console.log('Calculating...');
    const result = num + 10;
    cache[num] = result;
    return result;
  };
}

const add = memoizedAdd();

console.log(add(5)); // Calculating... 15
console.log(add(5)); // From cache 15
Example 3: Currying / Partial Application

Partial application is useful for creating specialised functions on the fly.

function greet(greeting) {
  return function(name) {
    return `${greeting}, ${name}`;
  };
}

const sayHello = greet('Hello');
console.log(sayHello('Alice')); // Hello, Alice

Closures are powerful and form the basis of data privacy, currying, and memoization.


3. What are higher-order functions?

Higher-order functions are those that:

  • Take one or more functions as arguments, or
  • Return a function as a result.
function greet(fn) {
  return function(name) {
    return fn(name);
  };
}

const sayHello = greet(name => `Hello, ${name}`);
console.log(sayHello('Alice')); // Hello, Alice

Common examples include map, filter, and reduce. These are built-in HOFs that take functions as arguments.

Example: Transform API response data
const users = [
  { id: 1, name: 'Alice', isActive: true },
  { id: 2, name: 'Bob', isActive: false },
  { id: 3, name: 'Charlie', isActive: true }
];

// Filter only active users
const activeUsers = users.filter(user => user.isActive);

// Extract user names
const names = activeUsers.map(user => user.name);

console.log(names); // ["Alice", "Charlie"]
Example 2: Debounce / Throttle

Used for search input, window resize, scroll, etc.

function debounce(fn, delay) {
  let timeout;
  return function (...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn.apply(this, args), delay);
  };
}

const handleSearch = debounce((query) => {
  console.log('Searching for:', query);
}, 300);

document.getElementById('search').addEventListener('input', (e) => {
  handleSearch(e.target.value);
});

4. JavaScript event loop explanation with code example

JavaScript is single-threaded, but handles concurrency through the event loop.

The event loop is a mechanism in JavaScript that continuously monitors the call stack and the task queue, ensuring that asynchronous operations like API calls, timers, and event listeners are executed correctly without blocking the main thread.

Here’s a breakdown:

  1. Call Stack: Executes synchronous code (line-by-line).
  2. Web APIs: Handles async tasks like setTimeout.
  3. Callback Queue: Holds setTimeout, event listeners.
  4. Microtask Queue: Holds promises (.then, catch, finally).
  5. Event Loop: Checks if the call stack is clear and pushes queued tasks.

Following is the example the UI freeze due to the blocking of Call Stack:

document.getElementById('btn').addEventListener('click', () => {
  alert('Starting...');

  // This blocks the UI
  const start = Date.now();
  while (Date.now() - start < 3000) {
    // Simulating heavy task
  }

  alert('Finished!');
});
Example of keep UI smooth using setTimeout:
document.getElementById('btn').addEventListener('click', () => {
  alert('Starting...');

  let iterations = 0;
  const totalIterations = 3000;
  const chunkSize = 100; // Do 100 iterations per chunk

  function processChunk() {
    const start = Date.now();

    while (Date.now() - start < 16 && iterations < totalIterations) {
      // Simulated work
      iterations++;
      // Do something useful here, like building a list or rendering
    }

    if (iterations < totalIterations) {
      // Schedule next chunk
      setTimeout(processChunk, 0);
    } else {
      alert('Finished!');
    }
  }

  processChunk(); // Kick off the first chunk
});

Another example of handling server response while keeping UI smooth:

button.addEventListener('click', () => {
  fetch('/api/user')
    .then(res => res.json())
    .then(data => {
      // This is in microtask queue
      console.log('Fetched user:', data);
    });

  console.log('Clicked'); // Runs before fetch completes
});

The click event is handled, then fetch is passed to Web APIs, result is queued as a microtask when ready. The UI stays responsive.


5. == vs === Which one should you use?

  • == performs loose equality comparison
  • === performs  a strict equality comparison, requires the operands to have the same type (as well as the same value).
0 == '0';  // true
0 === '0'; // false

6. What Is this in JavaScript?

The keyword this refers to the context in which a function is executed. Its value is determined by how the function is called, not where it is defined. This dynamic nature can sometimes make this challenging to understand.

const obj = {
  name: 'YT',
  greet() {
    console.log(this.name);
  }
};

obj.greet();       // YT
const greet = obj.greet;
greet();           // undefined (or global in non-strict mode)

Here is the article that explain in details about the this keyword.


7. Debounce vs Throttle interview question with example

Used to control the rate at which functions execute (e.g., during scrolling or typing).

Debounce delays execution until user stops triggering the function.

Throttle ensures a function is called at most once every X ms.

Example: Using Throttle to limit search API call if the user types rapidly, this limits the number of API calls to once every 500ms.
function throttle(fn, delay) {
  let lastCall = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastCall >= delay) {
      lastCall = now;
      fn(...args);
    }
  };
}

function search(query) {
  console.log('Searching for:', query);
  // Imagine: fetch(`/api/search?q=${query}`)
}

const throttledSearch = throttle(search, 500);

document.getElementById('search').addEventListener('input', (e) => {
  throttledSearch(e.target.value);
});

8. What are Promises and async/await?

A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. It acts as a placeholder for a value that may not be available immediately but will be at some point in the future. 

Imagine you order a pizza. You don’t get the pizza immediately, but the restaurant gives you a receipt. This receipt is like a Promise.

const promise = new Promise((resolve) => {
  setTimeout(() => resolve('Done'), 1000);
});

promise.then(res => console.log(res));

async/await simplifies promise chaining:

async function getData() {
  try {
    const res = await fetch('https://api.example.com/data');
    const data = await res.json();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

getData();

9. What are Arrow functions?

Arrow functions, introduced in ES6, provide a concise syntax for writing JavaScript functions. They are a shorthand for function expressions and are particularly useful for simple, one-line operations and callbacks. While they offer a shorter syntax, they also have some key differences, notably in how they handle the this keyword and how they are constructed. 

// Traditional
function add(a, b) {
  return a + b;
}

// Arrow function
const add = (a, b) => a + b;

Arrow functions do not have their own this. Instead, they inherit this from their surrounding lexical scope.

Other than that, Arrow function also comes with following limitations:

  • No arguments object
  • Not usable with new keyword
  • Cannot be used as generator functions

10. How does JavaScript handle modules?

JavaScript supports multiple module systems:

  • CommonJS (require, module.exports) — used in Node.js
  • ES Modules (import, export) — modern standard

Conclusion

Mastering JavaScript means going beyond just writing functions — it’s about understanding how the language really works. Concepts like closures, this, async handling, and the event loop frequently appear in real-world development and interviews alike.

Whether you’re building SPAs or preparing for a job switch, sharpening these fundamentals will elevate your skills and confidence.


Posted

in

by

Advertisement