Skip to the content.

Top 30 JavaScript Interview Questions and Answers for 2024

Prepare for your next JavaScript interview with confidence!

Whether you’re a seasoned developer or just starting your career in tech, this essential resource for 2024 will help you brush up on core concepts, from basic language features to advanced topics.

Level-1: Basic

  1. Is JavaScript single-threaded?

    Yes, JavaScript is single-threaded, meaning it has one call stack and memory heap, executing one set of instructions at a time. However, it supports asynchronous operations via callbacks, promises, and async/await to handle tasks like fetching data or user input without blocking the main thread.

  2. Explain the main component of the JavaScript Engine and how it works.

    JavaScript engines execute code and convert it into machine code. They include:

    • Parser: Converts code into an Abstract Syntax Tree (AST).
    • Interpreter: Generates bytecode from AST.
    • Optimizing Compiler: Produces optimized machine code using profiling data.
    • Garbage Collector: Manages memory by reclaiming unused objects.

    Example: Chrome’s V8 engine uses Ignition (interpreter), TurboFan (compiler), and Sparkplug (fast compiler).

  3. Explain the event loop in JavaScript.

    The event loop manages asynchronous tasks by monitoring the call stack, job queue, and task queue:

    • Call Stack: Executes functions.
    • Job Queue (Microtasks): Handles async/await, promises, process.nextTick().
    • Task Queue (Macrotasks): Handles setTimeout, setInterval callbacks.

    The event loop processes callbacks from the job queue or task queue when the call stack is empty.

  4. Difference between var, let, and const?

    • var: Function-scoped or globally scoped, can be re-declared and updated.
    • let: Block-scoped, can be updated but not re-declared within the same scope.
    • const: Block-scoped, cannot be updated or re-declared; must be initialized.
  5. Different data types in JavaScript?

    JavaScript has primitive data types and objects:

    • Primitive: String, Number, BigInt, Boolean, Undefined, Null, Symbol.
    • Object: Includes Arrays, Functions, and other objects.
  6. What is a callback function and callback hell?

    • Callback Function: A function passed as an argument to another function, executed after a task completes.

      function fetchData(url, callback) {
        setTimeout(() => {
          const data = 'Some data';
          callback(data);
        }, 1000);
      }
      
    • Callback Hell: Deeply nested callbacks leading to hard-to-read code.

      fs.readFile('file1.txt', (err, data1) => {
        fs.readFile('file2.txt', (err, data2) => {
          fs.readFile('file3.txt', (err, data3) => {
            // More nested callbacks
          });
        });
      });
      
  7. What is Promise and Promise chaining?

    • Promise: Represents the result of an asynchronous operation, with states: Pending, Fulfilled, and Rejected.

      const fetchData = new Promise((resolve, reject) => {
        setTimeout(() => resolve('Data'), 1000);
      });
      
    • Promise Chaining: Executes a series of asynchronous tasks sequentially.

      fetchData
        .then(data => fetchData2())
        .then(data2 => fetchData3())
        .catch(error => console.error(error));
      
  8. What is async/await?

    async/await is syntactic sugar for working with promises, making asynchronous code look synchronous.

    async function fetchData() {
      try {
        const data = await fetch('url').then(res => res.json());
        console.log(data);
      } catch (error) {
        console.error(error);
      }
    }
    
  9. Difference between == and === operators?

    • == (Loose Equality): Compares values for equality after type conversion.
    • === (Strict Equality): Compares values and types for equality without type conversion.
  10. Different ways to create an Object in JavaScript?

    • Object Literal:

      const obj = { key: 'value' };
      
    • Constructor Function:

      function Person(name) { this.name = name; }
      const person = new Person('John');
      
    • Object.create():

      const proto = { greet() { console.log('Hello'); } };
      const obj = Object.create(proto);
      
  11. What is rest and spread operator?

    • Rest Operator (...): Collects multiple elements into an array.

      function sum(...numbers) { return numbers.reduce((a, b) => a + b); }
      
    • Spread Operator (...): Expands an array into individual elements.

      const arr = [1, 2, 3];
      const newArr = [...arr, 4, 5];
      
  12. What is a higher-order function?

    A higher-order function is a function that takes another function as an argument or returns a function.

    function applyOperation(arr, operation) {
      return arr.map(operation);
    }
    

Level-2: Intermediate

  1. What is Closure? What are the use cases of Closures?

    A closure is a function that retains access to its lexical scope even when the function is executed outside that scope.

     function makeCounter() {
       let count = 0;
       return function() {
         count++;
         return count;
       };
     }
     const counter = makeCounter();
     console.log(counter()); // 1
    
  2. Explain the concept of hoisting in JavaScript.

    Hoisting is JavaScript’s behavior of moving variable and function declarations to the top of their containing scope during compilation.

     console.log(a); // undefined
     var a = 5;
    
  3. What is a Temporal Dead Zone?

    The Temporal Dead Zone (TDZ) refers to the period from the start of a block until a variable is declared and initialized with let or const, during which the variable cannot be accessed.

  4. What is a prototype chain? and Object.create() method?

    • Prototype Chain: A chain of objects linked through their prototypes, allowing properties and methods to be inherited.
    • Object.create(): Creates a new object with the specified prototype object.

      const proto = { greet() { console.log('Hello'); } };
      const obj = Object.create(proto);
      obj.greet(); // Hello
      
  5. What is the difference between call, apply, and bind methods?

    • call: Calls a function with a given this value and arguments.

      function greet(name) { console.log(`Hello, ${name}`); }
      greet.call(null, 'John');
      
    • apply: Similar to call, but arguments are passed as an array.

      greet.apply(null, ['John']);
      
    • bind: Creates a new function with a bound this value and optional arguments.

      const boundGreet = greet.bind(null, 'John');
      boundGreet(); // Hello, John
      
  6. What are lambda or arrow functions?

    Arrow functions provide a shorter syntax for writing functions and do not bind their own this.

     const add = (a, b) => a + b;
    
  7. What is the currying function?

    Currying is a technique of transforming a function with multiple arguments into a series of functions that each take a single argument.

     function multiply(a) {
       return function(b) {
         return a * b;
       };
     }
     const double = multiply(2);
     console.log(double(5)); // 10
    
  8. What are the features of ES6?

    ES6 introduced several features including:

    • Let and const for block-scoped variables.
    • Arrow functions for shorter syntax and lexical this.
    • Template literals for string interpolation.
    • Destructuring for extracting values from arrays and objects.
    • Default parameters for functions.
    • Classes for object-oriented programming.
    • Promises for better asynchronous programming.
    • Modules for modular code structure.

Level-3: Expert

  1. What is Execution context, execution stack, variable object, scope chain?

    • Execution Context: Environment where code is evaluated and executed.
    • Execution Stack: A stack data structure that keeps track of the function calls.
    • Variable Object: Stores variables, functions, and parameters of a function.
    • Scope Chain: The hierarchy of scopes that a function has access to.
  2. What is the priority of execution of callback, promise, setTimeout, process.nextTick()?

    The execution priority is:

    1. process.nextTick() - Executes after the current operation completes.
    2. Microtasks (Promises) - Executes before rendering and I/O tasks.
    3. Macrotasks (setTimeout, setInterval) - Executes after microtasks.
  3. What is the difference between synchronous and asynchronous functions?

    • Synchronous: Executes code line by line, blocking the execution of subsequent code until the current operation completes.
    • Asynchronous: Executes code independently of the main thread, allowing other operations to continue running.
  4. What are the different types of prototypal inheritance?

    • Prototype Inheritance: Objects inherit properties and methods from their prototype.
    • Constructor Inheritance: Involves creating instances of a constructor function and setting their prototype.
  5. What is the purpose of Object.assign and how does it work?

    Object.assign() copies properties from one or more source objects to a target object, returning the target object.

     const target = { a: 1 };
     const source = { b: 2 };
     Object.assign(target, source);
     console.log(target); // { a: 1, b: 2 }
    
  6. What is the this keyword in JavaScript?

    The this keyword refers to the object that is executing the current function. Its value depends on how the function is called:

    • Global context: this refers to the global object.
    • Object method: this refers to the object the method is called on.
    • Constructor function: this refers to the new instance being created.
  7. What are the differences between null and undefined?

    • null: Represents intentional absence of any value.
    • undefined: Represents a variable that has been declared but not yet assigned a value.
  8. What is the typeof operator and what are its possible return values?

    The typeof operator returns a string indicating the type of a variable or expression:

    • "undefined"
    • "object"
    • "boolean"
    • "number"
    • "bigint"
    • "string"
    • "symbol"
    • "function"
  9. What is a Symbol in JavaScript?

    A Symbol is a primitive data type that creates unique identifiers for object properties, ensuring that property names are unique.

     const sym = Symbol('description');
    
  10. What are the new features introduced in ES2024?

    ES2024 introduces several new features, such as:

    • Logical Assignment Operators: Combining logical operations with assignment.
    • WeakRefs: Weak references to objects for garbage collection.
    • Module Attributes: Enhancements for importing modules with specific attributes.

1. Is JavaScript Single-Threaded?

Yes, JavaScript is single-threaded, meaning it has one call stack and one memory heap. It executes one set of instructions at a time. JavaScript is synchronous and blocking, but it also supports asynchronous operations through callbacks, promises, async/await, and event listeners. These features allow JavaScript to perform tasks like data fetching and I/O operations without blocking the main thread.

2. Main Components of the JavaScript Engine

JavaScript engines, like those in browsers, execute JavaScript code and convert it into machine code.

Google Chrome’s V8 Engine:

  1. Ignition: Interpreter.
  2. TurboFan: Optimizing compiler.
  3. Sparkplug: Fast compiler between Ignition and TurboFan.

3. Event Loop in JavaScript

The Event Loop handles asynchronous tasks by monitoring the call stack and event queue:

The event loop checks if the call stack is empty and processes callbacks from the job or task queue as needed.

4. Difference Between var, let, and const

5. Different Data Types in JavaScript

JavaScript is dynamically typed. Primitive data types are immutable and represent single values:

Example:

const mySymbol = Symbol('key');
const obj = {
    [mySymbol]: 'value'
};

6. Callback Functions and Callback Hell

Callback Function: A function passed as an argument to another function to be executed later.

Example:

function fetchData(url, callback) {
  setTimeout(() => {
    const data = 'Some data from the server';
    callback(data);
  }, 1000);
}

function processData(data) {
  console.log('Processing data:', data);
}

fetchData('https://example.com/data', processData);

Callback Hell: Refers to deeply nested callbacks which make code hard to read and debug.

Example:

fs.readFile('file1.txt', 'utf8', function(err, data) {
  if (err) {
    console.error(err);
  } else {
    fs.readFile('file2.txt', 'utf8', function(err, data) {
      if (err) {
        console.error(err);
      } else {
        fs.readFile('file3.txt', 'utf8', function(err, data) {
          if (err) {
            console.error(err);
          } else {
            // Continue with more nested callbacks...
          }
        });
      }
    });
  }
});

Avoiding Callback Hell: Use Promises or async/await.

Using Promises:

const readFile = (file) => {
  return new Promise((resolve, reject) => {
    fs.readFile(file, 'utf8', (err, data) => {
      if (err) reject(err);
      else resolve(data);
    });
  });
};

readFile('file1.txt')
  .then(data1 => readFile('file2.txt'))
  .then(data2 => readFile('file3.txt'))
  .then(data3 => {
    // Continue with more promise-based code...
  })
  .catch(err => {
    console.error(err);
  });

7. Chaining Promises

Chaining multiple .then() methods to a Promise allows performing tasks in sequence:

new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
})
  .then(function (result) {
    console.log(result); // 1
    return result * 2;
  })
  .then(function (result) {
    console.log(result); // 2
    return result * 3;
  })
  .then(function (result) {
    console.log(result); // 6
    return result * 4;
  });

8. Async/Await

async/await simplifies working with Promises, avoiding callback hell and making code more readable:

async function fetchData() {
  try {
    const data = await fetch('https://example.com/data');
    const jsonData = await data.json();
    return jsonData;
  } catch (error) {
    throw error;
  }
}

// Using the async function
fetchData()
  .then(jsonData => {
    // Handle the retrieved data
  })
  .catch(error => {
    // Handle errors
  });

9. == vs. ===

Examples:

0 == false   // true
0 === false  // false
1 == "1"      // true
1 === "1"     // false
null == undefined  // true
null === undefined // false

10. Different Ways to Create an Object in JavaScript

a) Object Literals

let person = {
  firstName: 'John',
  lastName: 'Doe',
  greet() {
    return 'Hello, ' + this.firstName + ' ' + this.lastName;
  }
};

b) Constructor Function

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.greet = function() {
    return 'Hello, ' + this.firstName + ' ' + this.lastName;
  };
}

let person1 = new Person('John', 'Doe');
let person2 = new Person('Jane', 'Smith');

c) Object.create()

let personProto = {
  greet() {
    return 'Hello, ' + this.firstName + ' ' + this.lastName;
  }
};

let person = Object.create(personProto);
person.firstName = 'John';
person.lastName = 'Doe';

d) Class Syntax (ES6)

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  greet() {
    return 'Hello, ' + this.firstName + ' ' + this.lastName;
  }
}

let person = new Person('John', 'Doe');

e) Factory Functions

function createPerson(firstName, lastName) {
  return {
    firstName,
    lastName,
    greet() {
      return 'Hello, ' + this.firstName + ' ' + this.lastName;
    }
  };
}

let person1 = createPerson('John', 'Doe');
let person2 = createPerson('Jane', 'Smith');

f) Object.setPrototypeOf()

let personProto = {
  greet() {
    return 'Hello, ' + this.firstName + ' ' + this.lastName;
  }
};

let person = {};
person.firstName = 'John';
person.lastName = 'Doe';
Object.setPrototypeOf(person, personProto);

g) Object.assign()

let target = { a: 1, b: 2 };
let source = { b: 3, c: 4 };
let mergedObject = Object.assign({}, target, source);

h) Prototype Inheritance

function Animal(name) {
  this.name = name;
}

Animal.prototype.greet = function() {
  return 'Hello, I am ' + this.name;
};

function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

let myDog = new Dog('Max', 'Poodle');

i) Singleton Pattern

let singleton = (function() {
  let instance;

  function createInstance() {
    return {
      // properties and methods
    };
  }

  return {
    getInstance: function() {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

11. Rest and Spread Operators

Rest Operator

Used to collect multiple arguments into an array:

function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // Outputs 10

Spread Operator

Used to spread elements of an array or object:

const array1 = [1, 2, 3];
const array2 = [...array1, 4, 5];
console.log(array2); // [1, 2, 3, 4, 5]

15. Temporal Dead Zone

The Temporal Dead Zone (TDZ) is a behavior in JavaScript where variables declared with let or const remain uninitialized until their declaration is encountered. Accessing these variables before their declaration results in a ReferenceError.

16. Prototype Chain and Object.create()

Prototype Chain:

Object.create():

17. call, apply, and bind

call():

apply():

bind():

18. Arrow Functions

Arrow Functions provide a concise syntax for writing function expressions. They do not have their own this, arguments, or prototype.

const add = (x, y) => x + y;

19. Currying

Currying is a functional programming technique that transforms a function with multiple arguments into a series of functions, each taking a single argument.

function curryAdd(x) {
    return function(y) {
        return x + y;
    };
}

const add5 = curryAdd(5);
console.log(add5(3)); // Output: 8

20. Features of ES6

  1. Arrow Functions
  2. Block-Scoped Variables (let, const)
  3. Classes
  4. Modules
  5. Template Literals
  6. Default Parameters
  7. Rest and Spread Operators
  8. Destructuring Assignment
  9. Promises
  10. Map, Set, WeakMap, WeakSet
  11. Iterators and Generators
  12. Enhanced Object Literals

21. Execution Context, Stack, Variable Object, and Scope Chain

Execution Context:

Execution Stack (Call Stack):

Variable Object:

Scope Chain:

22. Priority of Execution of Callback, Promise, setTimeout, process.nextTick()

  1. process.nextTick(): Highest priority; executed immediately after the current operation completes.
  2. Promise: Executed after process.nextTick(), but before setTimeout().
  3. setTimeout(): Executed after promises.
  4. Callback: Lowest priority, executed after all the above phases.

23. Factory Function vs Generator Function

Factory Function: Returns a new object. Example:

function createPerson(name, age) {
  return {
    name: name,
    age: age,
    greet: function() {
      return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
    }
  };
}

const person1 = createPerson('Alice', 25);
const person2 = createPerson('Bob', 30);
console.log(person1.greet()); // Output: Hello, my name is Alice and I am 25 years old.
console.log(person2.greet()); // Output: Hello, my name is Bob and I am 30 years old.

Generator Function: Can be paused and resumed using yield. Example:

function* numberGenerator() {
  let i = 0;
  while (true) {
    yield i++;
  }
}

const gen = numberGenerator();
console.log(gen.next().value); // Output: 0
console.log(gen.next().value); // Output: 1
console.log(gen.next().value); // Output: 2

24. Cloning Objects (Shallow and Deep Copy)

Shallow Copy: Copies object references. Example:

const user = {
  name: "Kingsley",
  age: 28,
  job: "Web Developer"
};
const clone = user;

Deep Copy: Copies object values recursively.

a) JSON Methods:

const originalObject = { name: "Alice", age: 25 };
const deepCopy = JSON.parse(JSON.stringify(originalObject));

b) structuredClone:

const myDeepCopy = structuredClone(myOriginal);

c) Spread Operator (shallow copy):

const originalObject = { name: "Alice", age: 25 };
const deepCopy = {...originalObject};
deepCopy.name = "ravi";
console.log("originalObject", originalObject.name); // Alice

d) Object.assign (shallow copy):

const originalObject = { name: "Alice", age: 25 };
const shallowCopy = Object.assign({}, originalObject);

e) Recursion:

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) return obj;
  const newObj = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (Object.hasOwnProperty.call(obj, key)) {
      newObj[key] = deepCopy(obj[key]);
    }
  }
  return newObj;
}

const originalObject = { name: "Alice", nested: { age: 25 } };
const deepCopy = deepCopy(originalObject);

25. Making an Object Immutable

Object.freeze (Completely Immutable):

const obj = { name: 'Alice', age: 25 };
Object.freeze(obj);
obj.name = 'Bob'; // Not allowed
obj.address = '123 Street'; // Not allowed
delete obj.age; // Not allowed

Object.seal (Partially Immutable):

const obj = { name: 'Alice', age: 25 };
Object.seal(obj);
obj.name = 'Bob'; // Allowed
obj.address = '123 Street'; // Not allowed (no new properties)
delete obj.age; // Not allowed (existing properties cannot be deleted)

26. Event Flow: Capturing and Bubbling

Event flow involves:

  1. Event Capturing Phase: Travels from the root to the target.
  2. Event Target Phase: Reaches the target element.
  3. Event Bubbling Phase: Travels back from the target to the root.

Example:

<div id="parent">
  <button id="child">Click me!</button>
</div>
document.getElementById('parent').addEventListener('click', function() {
  console.log('Div clicked (capturing phase)');
}, true); // Capturing phase

document.getElementById('child').addEventListener('click', function() {
  console.log('Button clicked (target phase)');
});

document.getElementById('parent').addEventListener('click', function() {
  console.log('Div clicked (bubbling phase)');
});

27. Event Delegation

Attach a single event listener to a parent element:

var form = document.querySelector("#registration-form");

form.addEventListener("input", function(event) {
  console.log(event.target); // Log the field that was changed
});

28. Server-Sent Events (SSE)

SSE allows real-time updates from server to client.

Example:

if (typeof EventSource !== "undefined") {
  var source = new EventSource("sse_generator.js");
  source.onmessage = function(event) {
    document.getElementById("output").innerHTML += event.data + "<br>";
  };
}

29. Web Workers vs Service Workers

Web Workers: Run JavaScript code in the background, enabling concurrent execution.

Service Workers: Provide offline capabilities and background sync for Progressive Web Apps (PWAs).

30. Comparing Two JSON Objects

Using JSON.stringify:

const obj1 = { name: "Alice", age: 25 };
const obj2 = { name: "Alice", age: 25 };

const isEqual = JSON.stringify(obj1) === JSON.stringify(obj2);
console.log(isEqual); // true

Ref: Ravi Sharma - Medium