30 Must-Know JavaScript Interview Questions & Code Examples | SUDBTECH

30 Must-Know JavaScript Interview Questions & Code Examples | SUDBTECH

JavaScript remains one of the most popular languages for web development. Whether you’re starting your career or are a seasoned developer, these 30 interview questions along with code examples will help you articulate key concepts during your technical interview.

1. What is JavaScript?

Answer:

JavaScript is a high-level, interpreted programming language that is primarily used to create interactive and dynamic content on websites. It was originally developed to add interactivity to HTML pages and has since evolved into a full-fledged language that can run both in the browser (client-side) and on the server (server-side) through technologies like Node.js.

Key Characteristics of JavaScript:

  • Dynamic: JavaScript doesn’t require a pre-compilation step. It is executed in real-time by the browser or server, which means you can immediately test and see results.
  • Interpreted: Unlike compiled languages like C++ or Java, JavaScript code is executed directly by the browser (or runtime environment like Node.js) without the need for a separate compilation step.
  • Event-driven and asynchronous: JavaScript excels at handling events and asynchronous operations, like user input, HTTP requests, or timers, which allows for more interactive and responsive user interfaces.
  • Weakly typed: Variables in JavaScript can change types (for example, a variable can be a number and later be a string), which makes it flexible but also sometimes prone to errors.

Example Code:

<!DOCTYPE html>
<html>
  <head>
    <title>JavaScript Example</title>
  </head>
  <body>
    <h1 id="greeting">Hello, World!</h1>
    <script>
      // This script changes the text content of the h1 element.
      document.getElementById('greeting').textContent = 'Hello from JavaScript!';
    </script>
  </body>
</html>

2. How does JavaScript differ from Java?

Answer:
Despite similar names, JavaScript is an interpreted language designed for web interactivity, while Java is a compiled, object-oriented language used for building large-scale applications.

Example:
In JavaScript, you can write a simple function and run it directly in the browser, whereas Java requires a compilation step.

// JavaScript function
function greet() {
  console.log("Hello from JavaScript!");
}
greet();

3. What is Hoisting in JavaScript?

Answer:
Hoisting is JavaScript's default behavior of moving declarations to the top of the current scope. Only the declarations are hoisted—not the initializations.

Example Code:

console.log(x); // Outputs: undefined (declaration is hoisted)
var x = 5;

Explanation: The declaration var x; is hoisted to the top, but the assignment x = 5 remains in place.

4. Can you explain what a Closure is?

Answer:

In simple terms, a closure is a function that "remembers" the lexical scope (i.e., the variables and parameters) from where it was created, even after the outer function has finished executing. This means that the inner function still has access to variables and parameters from its outer function, even after that outer function has completed.

Key Concepts of Closures:

  • Lexical Scope: This refers to the context in which a function was created. A function can access variables from its own scope and from the outer (enclosing) scope.
  • Access to Outer Function's Variables: Even after the outer function has returned, the inner function still has access to the variables in the outer function's scope.

How Closures Work:

When you create a function inside another function, the inner function forms a closure by capturing and "remembering" the variables from the outer function's scope. These variables stay accessible even after the outer function finishes executing.

Example Code:

function createCounter() {
  let count = 0;  // `count` is part of the outer function's scope
  return function() {
    count++;  // Inner function has access to `count`
    return count;  // Returning the updated value of `count`
  };
}

const counter = createCounter();  // `createCounter` has executed, but `count` persists
console.log(counter());  // 1
console.log(counter());  // 2
console.log(counter());  // 3

Explanation of the Example:

  • createCounter() is an outer function that defines a local variable count.
  • Inside createCounter(), there is a returning inner function that increments the count and returns its value.
  • When createCounter() is called, it returns the inner function. This inner function is a closure because it "remembers" and retains access to the count variable even after createCounter() has finished executing.
  • The variable count is not destroyed when createCounter() finishes—because of the closure, the inner function still has access to it.
  • Every time you call counter(), the inner function increments count and returns its updated value.

Why is this Important?

  • Data Encapsulation: Closures allow for the creation of private variables and functions. You can encapsulate data inside a function and expose only certain parts of it, keeping other parts private and inaccessible from the outside.
  • State Preservation: The closure allows functions to "remember" and update state over time. This is particularly useful for things like counters, event handlers, or managing private state in object-like structures.

Another Example with Practical Use:

Let’s say you want to create a private variable that can only be accessed or modified by specific functions:

function createPerson(name) {
  let age = 0;  // `age` is private to this closure

  return {
    getName: function() {
      return name;
    },
    getAge: function() {
      return age;
    },
    incrementAge: function() {
      age++;  // Modify the private `age`
    }
  };
}

const person = createPerson("John");
console.log(person.getName());  // "John"
console.log(person.getAge());   // 0
person.incrementAge();
console.log(person.getAge());   // 1
person.incrementAge();
console.log(person.getAge());   // 2

Explanation:

  • createPerson() creates a closure around the name and age variables.
  • The age variable is private—it can’t be accessed directly from outside the closure.
  • The only way to interact with age is through the getter (getAge()) and setter (incrementAge()) functions, which are exposed by the object returned by createPerson().
  • Even though createPerson() has completed executing, the age variable persists because it is captured by the closure and accessible by the inner functions.

Real-World Use Cases for Closures:

  1. Function Factories: You can use closures to create functions dynamically, with custom behavior based on input parameters.
  2. Private Variables: As shown in the createPerson() example, closures allow you to create private variables and functions, which helps in data encapsulation and creating more modular, maintainable code.
  3. Event Handlers: Closures are often used in event handlers (like in a web browser) where you need to retain access to certain values or states even after the event handler function is executed.
  4. Callbacks and Promises: Closures are used extensively in asynchronous programming with callbacks, promises, or async/await, where inner functions remember the context and state from their outer scope.

5. What are the Primitive Data Types in JavaScript?

Answer:
JavaScript has several primitive data types: String, Number, Boolean, Undefined, Null, Symbol (ES6), and BigInt (ES2020).

Example Code:

let name = "Alice";       // String
let age = 30;             // Number
let isStudent = false;    // Boolean
let address;              // Undefined
let phone = null;         // Null
let id = Symbol("id");    // Symbol
let largeNumber = BigInt(12345678901234567890n); // BigInt

6. What is the Difference Between null and undefined?

Answer:
undefined means a variable has been declared but not assigned a value, whereas null is an explicit assignment indicating “no value.”

Example Code:

let a;
console.log(a); // undefined

let b = null;
console.log(b); // null

7. What is an Immediately Invoked Function Expression (IIFE)?

Answer:
An IIFE is a function that runs as soon as it is defined, creating its own scope and preventing global namespace pollution.

Example Code:

(function() {
  const message = "IIFE executed!";
  console.log(message);
})();

8. What is a Callback Function?

Answer:

A callback function is a function that is passed as an argument to another function. The outer function then calls the callback function to complete a task or handle something after an operation is finished. Callbacks are commonly used for asynchronous operations (like data fetching, timers, etc.), but they can also be used in synchronous operations.

Why are Callbacks Useful?

Callbacks allow us to:

  1. Handle asynchronous operations: Instead of blocking code execution, callbacks let you run code after a task (like loading data from a server) has completed.
  2. Improve code organization: By passing functions as arguments, you can abstract and reuse logic more effectively.
  3. Event handling: Callbacks are often used in event-driven programming, such as listening for button clicks, mouse movements, or form submissions.

Example of a Callback Function:

function fetchData(callback) {
  setTimeout(() => {
    // Simulating an asynchronous task (like fetching data)
    callback("Data loaded");
  }, 1000); // Wait for 1 second
}

fetchData((data) => {
  console.log(data); // "Data loaded" after 1 second
});

Explanation of the Example:

  • fetchData(callback): This function accepts a callback as an argument. Inside fetchData(), we simulate an asynchronous operation (like fetching data from an API) using setTimeout().
  • Callback function: The callback function ((data) => { console.log(data); }) is executed once the asynchronous operation is finished. In this case, after 1 second, it logs "Data loaded" to the console.
  • Asynchronous behavior: Without the callback, we wouldn't be able to log the data after 1 second. The callback is called after the setTimeout() delay, allowing us to handle the result of the operation.

Synchronous vs. Asynchronous Callbacks

  • Synchronous Callbacks: These are executed immediately in the flow of the program. For example, in array operations like map(), filter(), etc., the callback is called synchronously.
  • Example of a Synchronous Callback:
  • const numbers = [1, 2, 3, 4];
    
    const doubledNumbers = numbers.map((num) => {
      return num * 2; // Callback function is executed immediately
    });
    
    console.log(doubledNumbers); // [2, 4, 6, 8]
    
  • Asynchronous Callbacks: These are executed after a certain event or operation is completed, often involving tasks like reading a file, making a network request, or waiting for a timer.
  • Example of an Asynchronous Callback:
  • function fetchData(callback) {
      setTimeout(() => {
        callback("Data loaded after 2 seconds");
      }, 2000);
    }
    
    console.log("Fetching data...");
    fetchData((message) => {
      console.log(message);  // "Data loaded after 2 seconds"
    });
    console.log("Waiting...");
    
    • Here, the fetchData function simulates an asynchronous task (like a network request). The console.log("Waiting...") is executed immediately, while the callback console.log(message) is called after the 2-second delay.

Callback Example in Event Handling:

Callbacks are often used in event handling, like responding to a button click:

document.getElementById('myButton').addEventListener('click', function() {
  alert('Button clicked!');
});

  • In this example, the function passed to addEventListener is a callback that will be executed when the button is clicked.

Callback Hell (Pyramid of Doom)

One important concept to be aware of when using callbacks extensively is callback hell (also called "pyramid of doom"). This happens when you nest callbacks within callbacks, making the code hard to read and maintain.

Example of Callback Hell:

fetchData((data1) => {
  processData(data1, (processedData1) => {
    saveData(processedData1, (savedData) => {
      console.log(savedData);
    });
  });
});

This nested structure can quickly become difficult to manage. It’s often referred to as "callback hell."

How to Avoid Callback Hell?

You can avoid callback hell by:

  1. Using Promises: Promises provide a cleaner, more readable way to handle asynchronous operations.
  2. Using async/await: This syntax makes asynchronous code look more like synchronous code, improving readability.

9. What is a Promise in JavaScript?

Answer:
A Promise represents the eventual result of an asynchronous operation, letting you attach callbacks for success or failure.

Example Code:

const promise = new Promise((resolve, reject) => {
  let success = true;
  if (success) {
    resolve("Promise resolved!");
  } else {
    reject("Promise rejected!");
  }
});

promise
  .then(result => console.log(result))
  .catch(error => console.error(error));

10. What is Async/Await?

Answer:
async/await is syntactic sugar built on promises, enabling easier-to-read asynchronous code.

Example Code:

async function fetchUser() {
  try {
    const response = await fetch('https://api.example.com/user');
    const user = await response.json();
    console.log(user);
  } catch (error) {
    console.error("Error fetching user:", error);
  }
}

fetchUser();

11. Explain the Event Loop in JavaScript

Answer:
The event loop allows JavaScript to perform non-blocking operations by moving tasks to a queue and executing them when the call stack is empty.

Example Code:

console.log("Start");

setTimeout(() => {
  console.log("Timeout executed");
}, 0);

console.log("End");

// Output:
// Start
// End
// Timeout executed

Explanation: Even with a 0 ms delay, the setTimeout callback is executed after the current call stack is empty.

12. What is Prototypal Inheritance?

Answer:
JavaScript uses prototypal inheritance where objects inherit properties and methods from other objects through the prototype chain.

Example Code:

const person = {
  greet() {
    console.log("Hello!");
  }
};

const student = Object.create(person);
student.study = function() {
  console.log("Studying...");
};

student.greet();  // Inherited method
student.study();  // Own method

13. What is the Difference Between == and ===?

Answer:
== compares values after type coercion, while === compares both value and type.

Example Code:

console.log(5 == "5");  // true (type coercion)
console.log(5 === "5"); // false (strict equality)

14. Explain Call, Apply, and Bind Methods

Answer:

  • call: Invokes a function with a given this value and arguments provided individually.
  • apply: Similar to call, but arguments are provided as an array.
  • bind: Returns a new function with a bound this value and optionally preset arguments.

Example Code:

function showInfo(city, country) {
  console.log(`${this.name} lives in ${city}, ${country}`);
}

const user = { name: "Alice" };

// Using call
showInfo.call(user, "Paris", "France");

// Using apply
showInfo.apply(user, ["London", "UK"]);

// Using bind
const boundShowInfo = showInfo.bind(user, "New York", "USA");
boundShowInfo();

15. What are Arrow Functions?

Answer:
Arrow functions provide a shorter syntax and do not have their own this, making them useful for preserving the context of the surrounding code.

Example Code:

const numbers = [1, 2, 3, 4];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8]

16. What are var, let, and const?

Answer:

  • var: Function-scoped, can be re-assigned and re-declared.
  • let: Block-scoped, can be re-assigned but not re-declared in the same block.
  • const: Block-scoped, cannot be re-assigned after declaration.

Example Code:

var a = 10;
let b = 20;
const c = 30;

a = 15; // allowed
b = 25; // allowed
// c = 35; // Error: Assignment to constant variable!

17. What is the Module Pattern in JavaScript?

Answer:
The module pattern encapsulates code within a function scope and exposes only the necessary parts, helping to avoid polluting the global namespace.

Example Code:

const myModule = (function() {
  let privateVar = "secret";

  function privateMethod() {
    console.log("Accessing:", privateVar);
  }

  return {
    publicMethod: function() {
      privateMethod();
    }
  };
})();

myModule.publicMethod(); // Outputs: Accessing: secret

18. What is JSON?

Answer:
JSON (JavaScript Object Notation) is a lightweight data-interchange format that is easy to read and write. It is commonly used for data exchange between a server and a client.

Example Code:

const jsonString = '{"name": "Alice", "age": 30}';
const userObj = JSON.parse(jsonString);
console.log(userObj.name); // Alice

const newJson = JSON.stringify(userObj);
console.log(newJson); // {"name":"Alice","age":30}

19. What is the Difference Between Synchronous and Asynchronous Code?

Answer:
Synchronous code executes sequentially, while asynchronous code allows tasks to run concurrently (e.g., network requests, file I/O), preventing the program from blocking.

Example Code (Synchronous):

console.log("Step 1");
console.log("Step 2");
console.log("Step 3");

Example Code (Asynchronous):

console.log("Start");
setTimeout(() => {
  console.log("Async Step");
}, 1000);
console.log("End");

// Output:
// Start
// End
// Async Step (after 1 second)

20. What is a Higher Order Function?

Answer:
A higher order function is a function that takes another function as an argument or returns one as a result. Common examples are map(), filter(), and reduce().

Example Code:

const numbers = [1, 2, 3, 4];
const squares = numbers.map(num => num * num);
console.log(squares); // [1, 4, 9, 16]

21. Explain Event Bubbling and Capturing

Answer:

  • Event Bubbling: The event starts at the most specific element and bubbles up to its parent elements.
  • Event Capturing: The event starts at the top (outermost) element and propagates down to the target element.

Example Code (Bubbling):

<div id="parent" style="padding:20px; border:1px solid black;">
  Parent
  <button id="child">Child</button>
</div>

<script>
  document.getElementById('parent').addEventListener('click', () => {
    console.log("Parent clicked");
  });

  document.getElementById('child').addEventListener('click', (e) => {
    console.log("Child clicked");
    // e.stopPropagation(); // Uncomment to stop bubbling
  });
</script>

22. What are Debouncing and Throttling?

Answer:

  • Debouncing: Delays the execution of a function until after a specified wait time has elapsed since the last time it was invoked.
  • Throttling: Limits a function to run at most once every specified period.

Example Code (Debounce):

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

window.addEventListener('resize', debounce(() => {
  console.log("Resize event debounced");
}, 500));

Example Code (Throttle):

function throttle(fn, limit) {
  let inThrottle;
  return function(...args) {
    if (!inThrottle) {
      fn.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

window.addEventListener('scroll', throttle(() => {
  console.log("Scroll event throttled");
}, 1000));

23. What is CORS?

Answer:
CORS (Cross-Origin Resource Sharing) is a mechanism that allows resources on a web page to be requested from another domain. It is controlled via HTTP headers on the server.

Example Code (Client-Side Fetch with CORS):

fetch('https://api.example.com/data', {
  method: 'GET',
  mode: 'cors'
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error("CORS error:", error));

Note: The server must send the appropriate CORS headers to allow the request.

24. What Does the "this" Keyword Represent?

Answer:
The this keyword refers to the object that is executing the current function. Its value depends on the invocation context.

Example Code:

const person = {
  name: "Alice",
  greet: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

person.greet(); // "Hello, my name is Alice"

function show() {
  console.log(this);
}

show(); // In non-strict mode: the global object (window in browsers)

25. What is Recursion in JavaScript?

Answer:
Recursion is when a function calls itself to solve a problem that can be broken down into smaller, similar problems.

Example Code (Factorial):

function factorial(n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

console.log(factorial(5)); // 120

26. What is the Spread Operator?

Answer:
The spread operator (...) allows an iterable (like an array or object) to be expanded into individual elements.

Example Code:

// For arrays:
const numbers = [1, 2, 3];
const newNumbers = [...numbers, 4, 5];
console.log(newNumbers); // [1, 2, 3, 4, 5]

// For objects:
const person = { name: "Alice", age: 30 };
const updatedPerson = { ...person, age: 31 };
console.log(updatedPerson); // { name: "Alice", age: 31 }

27. What is Destructuring?

Answer:
Destructuring allows you to unpack values from arrays or properties from objects into distinct variables.

Example Code:

// Array destructuring:
const numbersArr = [10, 20, 30];
const [first, second, third] = numbersArr;
console.log(first, second, third); // 10 20 30

// Object destructuring:
const user = { username: "alice123", email: "alice@example.com" };
const { username, email } = user;
console.log(username, email); // alice123 alice@example.com

28. What is "Strict Mode" in JavaScript?

Answer:
Strict mode is a way to opt into a restricted variant of JavaScript, which catches common errors and unsafe actions.

Example Code:

"use strict";

function strictFunction() {
  // In strict mode, this will throw an error if you assign to an undeclared variable.
  // undeclaredVar = 10; // Uncommenting this line will throw an error.
  console.log("Strict mode enabled");
}

strictFunction();

29. What are the Different Ways to Create Objects in JavaScript?

Answer:
Objects can be created in several ways:

  • Object Literals: Using { key: value }
  • Constructor Functions: Using the new keyword
  • ES6 Classes: Syntactic sugar over constructor functions
  • Object.create(): Creating an object with a specified prototype

Example Code:

// Object literal:
const objLiteral = { name: "Alice", age: 30 };

// Constructor function:
function Person(name, age) {
  this.name = name;
  this.age = age;
}
const person1 = new Person("Bob", 25);

// ES6 Class:
class Animal {
  constructor(species) {
    this.species = species;
  }
}
const animal1 = new Animal("Cat");

// Using Object.create():
const prototypeObj = { greet() { console.log("Hi!"); } };
const objWithProto = Object.create(prototypeObj);
objWithProto.greet(); // "Hi!"

30. What is ES6 (ECMAScript 2015)?

Answer:
ES6 is a major update to JavaScript that introduced new features such as arrow functions, classes, template literals, destructuring, modules, promises, and more. These features improve code readability and developer productivity.

Example Code (ES6 Features):

// Arrow function:
const add = (a, b) => a + b;
console.log(add(5, 3)); // 8

// Template literal:
const name = "Alice";
console.log(`Hello, ${name}!`); // Hello, Alice!

// Destructuring:
const [x, y] = [10, 20];
console.log(x, y); // 10 20

// Class:
class Car {
  constructor(make, model) {
    this.make = make;
    this.model = model;
  }
  display() {
    console.log(`Car: ${this.make} ${this.model}`);
  }
}
const myCar = new Car("Toyota", "Corolla");
myCar.display(); // Car: Toyota Corolla

Conclusion

These 30 questions cover both basic and advanced topics in JavaScript, complete with practical code examples to illustrate key concepts. Reviewing and practicing these examples will help you build a strong foundation for your interview. Happy coding and best of luck with your interview preparation!


0 Comments