Learn Key JavaScript Concepts: 100+ Interview Questions with & Code Examples

Learn Key JavaScript Concepts: 100+ Interview Questions with & Code Examples

Dive into JavaScript: 100+ Key Interview Questions with Code Answers

Table of contents

Introduction

Hello fellow developers! If you are appearing for any front-end profile interview, these basic task-based 60 questions, and 40 advance questions along with code snippets as answers, provide a practical and efficient way to learn JavaScript. This collection is designed to help you not only understand JavaScript fundamentals but also build the logical and problem-solving skills crucial for tackling real-world challenges in front-end development.

From manipulating the DOM and handling events to working with arrays, objects, and modern ES6+ features, these tasks cover a comprehensive range of topics. Whether you're refreshing your skills or preparing for technical rounds, this structured approach ensures you’re ready to demonstrate your proficiency in JavaScript.

So, gear up, practice diligently, and let these exercises guide you toward acing your interviews and excelling as a front-end developer!

Basic task-based 60 questions

1. Variable Declaration

Q: What is the difference between var, let, and const? Write a code example showing their scope differences.
A:

function testScope() {
  if (true) {
    var a = "I am var";
    let b = "I am let";
    const c = "I am const";
  }
  console.log(a); // Accessible
  console.log(b); // Error
  console.log(c); // Error
}
testScope();

2. Hoisting

Q: Explain hoisting in JavaScript with an example.
A:

console.log(a); // undefined (hoisted)
var a = 10;
console.log(b); // Error (not hoisted)
let b = 20;

3. Closures

Q: Write a function to demonstrate closures in JavaScript.
A:

function outerFunction() {
  let counter = 0;
  return function innerFunction() {
    counter++;
    return counter;
  };
}
const increment = outerFunction();
console.log(increment()); // 1
console.log(increment()); // 2

4. Event Loop

Q: Explain the event loop with an example using setTimeout and Promise.
A:

console.log("Start");
setTimeout(() => console.log("Timeout"), 0);
Promise.resolve().then(() => console.log("Promise"));
console.log("End");
// Output: Start, End, Promise, Timeout

5. Prototypal Inheritance

Q: How does inheritance work in JavaScript?
A:

function Parent() {
  this.name = "Parent";
}
Parent.prototype.greet = function () {
  console.log("Hello from " + this.name);
};
function Child() {
  Parent.call(this);
  this.name = "Child";
}
Child.prototype = Object.create(Parent.prototype);
const child = new Child();
child.greet(); // Hello from Child

6. Callback Functions

Q: Write a function using a callback.
A:

function greet(name, callback) {
  console.log("Hi " + name);
  callback();
}
greet("Joe", () => {
  console.log("Callback executed!");
});

7. Promises

Q: Create a Promise that resolves after 2 seconds.
A:

const promise = new Promise((resolve) => {
  setTimeout(() => resolve("Resolved!"), 2000);
});
promise.then((msg) => console.log(msg));

8. Async/Await

Q: Write an async function that fetches data.
A:

async function fetchData() {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts");
  const data = await response.json();
  console.log(data);
}
fetchData();

9. Array Methods

Q: Write a code snippet using map, filter, and reduce.
A:

const numbers = [1, 2, 3, 4];
const doubled = numbers.map((n) => n * 2);
const even = numbers.filter((n) => n % 2 === 0);
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(doubled, even, sum);

10. Destructuring

Q: Use destructuring to extract values from an array and object.
A:

const arr = [1, 2, 3];
const [a, b] = arr;

const obj = { x: 10, y: 20 };
const { x, y } = obj;

console.log(a, b, x, y); // 1, 2, 10, 20

11. Rest and Spread Operators

Q: Write a function using rest and spread operators.
A:

function sum(...nums) {
  return nums.reduce((acc, n) => acc + n, 0);
}
console.log(sum(1, 2, 3)); // 6

const arr1 = [1, 2];
const arr2 = [3, 4];
console.log([...arr1, ...arr2]); // [1, 2, 3, 4]

12. ES6 Classes

Q: Create a class in JavaScript with a constructor and method.
A:

class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}
const person = new Person("Joe");
person.greet();

13. Debouncing

Q: Write a debouncing function.
A:

function debounce(func, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => func(...args), delay);
  };
}
const log = debounce(() => console.log("Debounced!"), 1000);
log();

14. Throttling

Q: Write a throttling function.
A:

function throttle(func, limit) {
  let inThrottle;
  return function (...args) {
    if (!inThrottle) {
      func(...args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
}
const log = throttle(() => console.log("Throttled!"), 1000);
log();

15. Default Parameters

Q: Demonstrate the use of default parameters in JavaScript.
A:

function greet(name = "Guest") {
  console.log(`Hello, ${name}`);
}
greet(); // Hello, Guest
greet("Joe"); // Hello, Joe

16. Template Literals

Q: Write a function that uses template literals.
A:

function describePerson(name, age) {
  console.log(`My name is ${name} and I am ${age} years old.`);
}
describePerson("Joe", 25);

17. Object Methods

Q: Demonstrate Object.keys, Object.values, and Object.entries.
A:

const obj = { a: 1, b: 2, c: 3 };
console.log(Object.keys(obj)); // ['a', 'b', 'c']
console.log(Object.values(obj)); // [1, 2, 3]
console.log(Object.entries(obj)); // [['a', 1], ['b', 2], ['c', 3]]

18. Optional Chaining

Q: Use optional chaining to safely access properties.
A:

const user = { name: "Joe", address: { city: "New York" } };
console.log(user?.address?.city); // New York
console.log(user?.contact?.phone); // undefined

19. Nullish Coalescing Operator

Q: Use the nullish coalescing operator (??).
A:

const name = null;
const defaultName = name ?? "Guest";
console.log(defaultName); // Guest

20. Spread with Objects

Q: Merge two objects using the spread operator.
A:

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 3, c: 4 }

21. Symbol

Q: Create a symbol and use it as an object property.
A:

const sym = Symbol("unique");
const obj = { [sym]: "value" };
console.log(obj[sym]); // value

22. Iterators

Q: Write an iterator for a custom object.
A:

const iterable = {
  data: [1, 2, 3],
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.data.length) {
          return { value: this.data[index++], done: false };
        }
        return { done: true };
      },
    };
  },
};
for (const value of iterable) {
  console.log(value);
}

23. Generators

Q: Create a generator function.
A:

function* generatorFunc() {
  yield 1;
  yield 2;
  yield 3;
}
const gen = generatorFunc();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

24. Set

Q: Demonstrate Set operations in JavaScript.
A:

const set = new Set([1, 2, 3, 1]);
set.add(4);
set.delete(2);
console.log(set.has(1)); // true
console.log([...set]); // [1, 3, 4]

25. Map

Q: Demonstrate Map operations in JavaScript.
A:

const map = new Map();
map.set("a", 1);
map.set("b", 2);
console.log(map.get("a")); // 1
map.delete("b");
console.log(map.has("b")); // false

26. WeakMap and WeakSet

Q: Explain WeakMap and WeakSet with examples.
A:

let obj = { key: "value" };
const weakMap = new WeakMap();
weakMap.set(obj, "WeakMap value");
console.log(weakMap.get(obj)); // WeakMap value
obj = null; // Object removed from memory

const weakSet = new WeakSet();
weakSet.add(obj); // Error if obj is null

27. This Keyword

Q: Demonstrate this keyword in different contexts.
A:

const obj = {
  name: "Joe",
  greet() {
    console.log(this.name);
  },
};
obj.greet(); // Joe

function globalGreet() {
  console.log(this); // Window (in browsers)
}
globalGreet();

28. Arrow Functions

Q: How do arrow functions differ from regular functions?
A:

const regularFunc = function () {
  console.log(this); // Dynamic (depends on call site)
};
const arrowFunc = () => {
  console.log(this); // Lexical (inherits from parent scope)
};
regularFunc();
arrowFunc();

29. Function Currying

Q: Implement function currying in JavaScript.
A:

function multiply(a) {
  return (b) => a * b;
}
const double = multiply(2);
console.log(double(5)); // 10

30. Event Delegation

Q: Explain event delegation with a code example.
A:

document.querySelector("#parent").addEventListener("click", (e) => {
  if (e.target && e.target.matches("button.child")) {
    console.log("Child button clicked");
  }
});

31. Deep and Shallow Copy

Q: Explain the difference between deep and shallow copy with examples.
A:

const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
shallowCopy.b.c = 5; // Affects the original object
console.log(obj.b.c); // 5

const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.b.c = 10; // Does not affect the original object
console.log(obj.b.c); // 5

32. JSON Methods

Q: Demonstrate JSON.stringify and JSON.parse.
A:

const obj = { name: "Joe", age: 25 };
const jsonString = JSON.stringify(obj);
console.log(jsonString); // '{"name":"Joe","age":25}'
const parsedObj = JSON.parse(jsonString);
console.log(parsedObj); // { name: "Joe", age: 25 }

33. Module System

Q: Explain import and export in JavaScript modules.
A:

// math.js
export const add = (a, b) => a + b;

// main.js
import { add } from "./math.js";
console.log(add(2, 3)); // 5

34. Web Storage API

Q: Use localStorage and sessionStorage.
A:

localStorage.setItem("name", "Joe");
console.log(localStorage.getItem("name")); // Joe
sessionStorage.setItem("age", "25");
console.log(sessionStorage.getItem("age")); // 25

35. Fetch API with Error Handling

Q: Perform a GET request and handle errors.
A:

fetch("https://jsonplaceholder.typicode.com/posts")
  .then((response) => {
    if (!response.ok) throw new Error("Network error");
    return response.json();
  })
  .then((data) => console.log(data))
  .catch((error) => console.error(error));

36. Async/Await with Error Handling

Q: Handle errors using try-catch with async/await.
A:

async function fetchData() {
  try {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    if (!response.ok) throw new Error("Network error");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}
fetchData();

37. DOM Manipulation

Q: Add a new element to the DOM dynamically.
A:

const newDiv = document.createElement("div");
newDiv.textContent = "Hello, DOM!";
document.body.appendChild(newDiv);

38. Event Listeners

Q: Attach an event listener to a button.
A:

const button = document.querySelector("#myButton");
button.addEventListener("click", () => {
  console.log("Button clicked!");
});

39. Prevent Default Behavior

Q: Demonstrate how to prevent default behavior of a form submission.
A:

document.querySelector("form").addEventListener("submit", (e) => {
  e.preventDefault();
  console.log("Form submission prevented!");
});

40. Bubbling and Capturing

Q: Explain event bubbling and capturing with an example.
A:

document.querySelector("#parent").addEventListener(
  "click",
  () => console.log("Parent clicked!"),
  true // Use capturing phase
);
document.querySelector("#child").addEventListener("click", () => {
  console.log("Child clicked!");
});

41. Custom Events

Q: Create and dispatch a custom event.
A:

const event = new CustomEvent("myEvent", { detail: { message: "Hello!" } });
document.addEventListener("myEvent", (e) => {
  console.log(e.detail.message);
});
document.dispatchEvent(event);

42. Date and Time

Q: Get the current date and format it.
A:

const now = new Date();
console.log(now.toISOString()); // Current date in ISO format
console.log(now.toLocaleDateString()); // Local date format

43. Regular Expressions

Q: Validate an email address using regex.
A:

const email = "example@example.com";
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
console.log(isValid); // true

44. Error Handling

Q: Use try-catch for error handling.
A:

try {
  JSON.parse("{ malformed: json }");
} catch (error) {
  console.error("Error parsing JSON:", error.message);
}

45. Constructor Functions

Q: Create an object using a constructor function.
A:

function Person(name, age) {
  this.name = name;
  this.age = age;
}
const joe = new Person("Joe", 25);
console.log(joe.name); // Joe

46. ES6 Set Timeout/Interval

Q: Use setTimeout and setInterval.
A:

setTimeout(() => console.log("Timeout executed!"), 1000);
const interval = setInterval(() => console.log("Interval executed!"), 1000);
setTimeout(() => clearInterval(interval), 5000);

47. Call, Apply, and Bind

Q: Demonstrate call, apply, and bind.
A:

const obj = { name: "Joe" };
function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}
greet.call(obj, "Hello");
greet.apply(obj, ["Hi"]);
const boundGreet = greet.bind(obj, "Hey");
boundGreet();

48. Polyfills

Q: Create a polyfill for Array.prototype.map.
A:

Array.prototype.myMap = function (callback) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    result.push(callback(this[i], i, this));
  }
  return result;
};
console.log([1, 2, 3].myMap((n) => n * 2)); // [2, 4, 6]

49. Object Freezing

Q: Demonstrate Object.freeze.
A:

const obj = { a: 1 };
Object.freeze(obj);
obj.a = 2; // No effect
console.log(obj.a); // 1

50. Promises in Sequence

Q: Execute promises in sequence.
A:

const promises = [1, 2, 3].map(
  (num) => new Promise((resolve) => setTimeout(() => resolve(num), 1000))
);
promises.reduce((acc, curr) => acc.then(() => curr.then(console.log)), Promise.resolve());

51. Throttling

Q: Implement a throttling function in JavaScript.
A:

function throttle(func, delay) {
  let lastCall = 0;
  return function (...args) {
    const now = new Date().getTime();
    if (now - lastCall >= delay) {
      lastCall = now;
      func(...args);
    }
  };
}

const log = throttle(() => console.log("Throttled!"), 2000);
window.addEventListener("resize", log);

52. Debouncing

Q: Implement a debouncing function in JavaScript.
A:

function debounce(func, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => func(...args), delay);
  };
}

const log = debounce(() => console.log("Debounced!"), 2000);
window.addEventListener("resize", log);

53. Function Composition

Q: Create a function composition utility.
A:

const compose = (...functions) => (value) => 
  functions.reduceRight((acc, func) => func(acc), value);

const add = (x) => x + 1;
const double = (x) => x * 2;
const composedFunc = compose(add, double);
console.log(composedFunc(5)); // (5 * 2) + 1 = 11

54. Hoisting

Q: Explain hoisting with examples.
A:

console.log(a); // undefined (var hoisted, but not initialized)
var a = 10;

console.log(b); // ReferenceError (let and const are not hoisted in the same way)
let b = 20;

greet(); // Function hoisted
function greet() {
  console.log("Hello!");
}

55. Closures

Q: Create a closure and explain how it works.
A:

function outer() {
  let count = 0;
  return function inner() {
    count++;
    console.log(count);
  };
}

const increment = outer();
increment(); // 1
increment(); // 2

56. Promises with All, AllSettled, Race, and Any

Q: Demonstrate Promise.all, Promise.allSettled, Promise.race, and Promise.any.
A:

const promises = [
  Promise.resolve(1),
  Promise.reject("Error"),
  Promise.resolve(3),
];

Promise.all(promises)
  .then(console.log)
  .catch(console.error); // Error

Promise.allSettled(promises).then(console.log);
// [{status: 'fulfilled', value: 1}, {status: 'rejected', reason: 'Error'}, {status: 'fulfilled', value: 3}]

Promise.race(promises).then(console.log).catch(console.error); // 1

Promise.any(promises).then(console.log).catch(console.error); // 1 (ignores rejections)

57. Event Loop

Q: Explain the event loop with an example.
A:

console.log("Start");

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

Promise.resolve().then(() => console.log("Promise"));

console.log("End");
// Output: Start, End, Promise, Timeout

58. Callbacks

Q: Write a function that uses a callback.
A:

function fetchData(callback) {
  setTimeout(() => {
    callback("Data fetched");
  }, 1000);
}

fetchData((data) => console.log(data)); // Data fetched

59. Strict Mode

Q: Explain the purpose of "use strict" with examples.
A:

"use strict";
x = 10; // ReferenceError: x is not defined
console.log(x);

60. Asynchronous Iteration

Q: Use for-await-of to handle asynchronous iteration.
A:

const asyncIterable = {
  async *[Symbol.asyncIterator]() {
    yield "Hello";
    yield "Async";
    yield "Iteration";
  },
};

(async () => {
  for await (const word of asyncIterable) {
    console.log(word);
  }
})();
// Output: Hello, Async, Iteration

Advanced JavaScript Questions and Answers


1. What is Currying? Implement it.

A: Currying is the process of transforming a function with multiple arguments into a sequence of functions, each taking a single argument.

function curry(func) {
  return function curried(...args) {
    if (args.length >= func.length) {
      return func(...args);
    } else {
      return (...nextArgs) => curried(...args, ...nextArgs);
    }
  };
}

function sum(a, b, c) {
  return a + b + c;
}
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6

2. What is Memoization? Implement a memoized function.

A: Memoization is an optimization technique where function results are cached to avoid redundant computations.

function memoize(fn) {
  const cache = new Map();
  return function (...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
}

const fib = memoize((n) => (n <= 1 ? n : fib(n - 1) + fib(n - 2)));
console.log(fib(10)); // 55

3. Explain Prototypal Inheritance with an Example.

A: In JavaScript, objects can inherit from other objects via prototypes.

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

const joe = Object.create(person);
joe.name = "Joe";
joe.greet(); // Hello, my name is Joe

4. Implement a Custom Promise.all Method.

A:

function customPromiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    let completed = 0;
    promises.forEach((promise, index) => {
      Promise.resolve(promise)
        .then((value) => {
          results[index] = value;
          completed += 1;
          if (completed === promises.length) resolve(results);
        })
        .catch(reject);
    });
  });
}

const promises = [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)];
customPromiseAll(promises).then(console.log); // [1, 2, 3]

5. Implement a Singleton Pattern.

A:

const Singleton = (function () {
  let instance;
  return function () {
    if (!instance) {
      instance = this;
    }
    return instance;
  };
})();

const obj1 = new Singleton();
const obj2 = new Singleton();
console.log(obj1 === obj2); // true

6. What are WeakMap and WeakSet? Use Cases.

A: WeakMap and WeakSet allow for garbage collection of their keys when no other references exist.

let obj = { key: "value" };
const weakMap = new WeakMap();
weakMap.set(obj, "metadata");
obj = null; // The object is garbage-collected
console.log(weakMap); // WeakMap { <items unknown> }

7. Explain Debounce and Implement It Using Promises.

A: Debounce ensures a function is executed only after a specified delay since its last call.

function debounce(func, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => func(...args), delay);
  };
}

const log = debounce((msg) => console.log(msg), 1000);
log("Hello"); // Executed only after 1 second if no other calls occur

8. What is a Proxy? Implement a Logging Proxy.

A: A Proxy is used to define custom behavior for fundamental operations.

const handler = {
  get(target, prop) {
    console.log(`Accessing ${prop}`);
    return target[prop];
  },
  set(target, prop, value) {
    console.log(`Setting ${prop} to ${value}`);
    target[prop] = value;
    return true;
  },
};

const obj = new Proxy({ a: 1 }, handler);
console.log(obj.a); // Accessing a
obj.b = 2; // Setting b to 2

9. Explain Tail Call Optimization with an Example.

A: Tail call optimization occurs when a function makes a call as its last action, allowing stack reuse.

function factorial(n, acc = 1) {
  if (n === 0) return acc;
  return factorial(n - 1, acc * n); // Tail call
}
console.log(factorial(5)); // 120

10. Implement an Event Emitter.

A:

class EventEmitter {
  constructor() {
    this.events = {};
  }
  on(event, listener) {
    if (!this.events[event]) this.events[event] = [];
    this.events[event].push(listener);
  }
  emit(event, ...args) {
    if (this.events[event]) {
      this.events[event].forEach((listener) => listener(...args));
    }
  }
}

const emitter = new EventEmitter();
emitter.on("sayHello", (name) => console.log(`Hello, ${name}`));
emitter.emit("sayHello", "Joe"); // Hello, Joe

11. Explain and Implement Generators.

A: Generators produce a sequence of values using the yield keyword.

function* generateSequence() {
  yield 1;
  yield 2;
  yield 3;
}

const generator = generateSequence();
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
console.log(generator.next().value); // 3

12. What are Iterators? Implement a Custom Iterator.

A: Iterators are objects that allow sequential access to their elements.

const customIterable = {
  data: [1, 2, 3],
  [Symbol.iterator]() {
    let index = 0;
    const data = this.data;
    return {
      next() {
        if (index < data.length) {
          return { value: data[index++], done: false };
        }
        return { value: undefined, done: true };
      },
    };
  },
};

for (const item of customIterable) {
  console.log(item); // 1, 2, 3
}

13. Implement a Deep Clone Function.

A:

function deepClone(obj) {
  if (obj === null || typeof obj !== "object") return obj;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof Array) return obj.map(deepClone);
  if (obj instanceof Object) {
    return Object.keys(obj).reduce((acc, key) => {
      acc[key] = deepClone(obj[key]);
      return acc;
    }, {});
  }
}

const original = { a: 1, b: { c: 2 }, d: [3, 4] };
const clone = deepClone(original);
console.log(clone); // { a: 1, b: { c: 2 }, d: [3, 4] }

14. Explain the Difference Between Call, Apply, and Bind.

A:

function greet(greeting, punctuation) {
  console.log(`${greeting}, ${this.name}${punctuation}`);
}

const person = { name: "Joe" };

greet.call(person, "Hello", "!"); // Hello, Joe!
greet.apply(person, ["Hi", "?"]); // Hi, Joe?
const boundGreet = greet.bind(person, "Hey");
boundGreet("!"); // Hey, Joe!

15. What is a Symbol? Use Case.

A: Symbol is a unique and immutable data type primarily used as object keys.

const id = Symbol("id");
const user = {
  name: "Joe",
  [id]: 123,
};

console.log(user[id]); // 123
console.log(Object.keys(user)); // ["name"] (id is not enumerable)

16. Implement a Rate Limiter Using Closures.

A:

function rateLimiter(func, limit, interval) {
  let calls = 0;
  const queue = [];

  const execute = () => {
    if (queue.length === 0 || calls >= limit) return;
    calls++;
    queue.shift()();
    setTimeout(() => {
      calls--;
      execute();
    }, interval);
  };

  return (...args) => {
    queue.push(() => func(...args));
    execute();
  };
}

const limitedFunc = rateLimiter(() => console.log("Executed"), 2, 1000);
limitedFunc(); // Executed
limitedFunc(); // Executed
limitedFunc(); // Delayed

17. Explain Async/Await Error Handling with Examples.

A:

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

18. What is Object.freeze? Demonstrate Its Use.

A: Object.freeze makes an object immutable.

const obj = { a: 1 };
Object.freeze(obj);
obj.a = 2; // No effect
console.log(obj.a); // 1

19. Implement a Custom Map Function.

A:

Array.prototype.customMap = function (callback) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    result.push(callback(this[i], i, this));
  }
  return result;
};

const arr = [1, 2, 3];
console.log(arr.customMap((x) => x * 2)); // [2, 4, 6]

20. Explain Event Delegation with an Example.

A:

document.getElementById("parent").addEventListener("click", (event) => {
  if (event.target.tagName === "BUTTON") {
    console.log(`Button clicked: ${event.target.textContent}`);
  }
});
// Dynamically added buttons will also trigger the handler.

21. Implement a Retry Mechanism for Failed Promises.

A:

async function retry(func, retries = 3) {
  while (retries > 0) {
    try {
      return await func();
    } catch (error) {
      retries--;
      if (retries === 0) throw error;
    }
  }
}

retry(() => fetch("https://api.example.com"), 3)
  .then(console.log)
  .catch(console.error);

22. What Are Mixins? Implement One.

A: Mixins allow objects to share functionality.

const sayHiMixin = {
  sayHi() {
    console.log(`Hi, ${this.name}`);
  },
};

class User {
  constructor(name) {
    this.name = name;
  }
}

Object.assign(User.prototype, sayHiMixin);
const user = new User("Joe");
user.sayHi(); // Hi, Joe

23. Implement a Custom Reduce Function.

A:

Array.prototype.customReduce = function (callback, initialValue) {
  let acc = initialValue === undefined ? this[0] : initialValue;
  let startIndex = initialValue === undefined ? 1 : 0;

  for (let i = startIndex; i < this.length; i++) {
    acc = callback(acc, this[i], i, this);
  }
  return acc;
};

const arr = [1, 2, 3];
console.log(arr.customReduce((sum, num) => sum + num, 0)); // 6

24. Explain the Module Pattern.

A:

const counterModule = (function () {
  let count = 0;
  return {
    increment() {
      count++;
    },
    getCount() {
      return count;
    },
  };
})();

counterModule.increment();
console.log(counterModule.getCount()); // 1

25. Implement a Custom Event Bus.

A: An Event Bus is a pattern for managing communication between different parts of an application.

class EventBus {
  constructor() {
    this.events = {};
  }

  subscribe(event, callback) {
    if (!this.events[event]) this.events[event] = [];
    this.events[event].push(callback);
  }

  publish(event, ...args) {
    if (this.events[event]) {
      this.events[event].forEach((callback) => callback(...args));
    }
  }

  unsubscribe(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter((cb) => cb !== callback);
    }
  }
}

const bus = new EventBus();
const onEvent = (data) => console.log(`Event received with data: ${data}`);
bus.subscribe("testEvent", onEvent);
bus.publish("testEvent", "Hello!"); // Event received with data: Hello!
bus.unsubscribe("testEvent", onEvent);
bus.publish("testEvent", "Hello again!"); // No output

26. Explain and Implement Throttling.

A: Throttling ensures a function is executed at most once in a specified time frame.

function throttle(func, delay) {
  let lastCall = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastCall >= delay) {
      lastCall = now;
      func(...args);
    }
  };
}

const log = throttle((msg) => console.log(msg), 1000);
log("Hello"); // Executed immediately
log("World"); // Ignored if called within 1 second

27. Explain Reflect and Its Use Cases.

A: The Reflect API provides methods for interceptable JavaScript operations.

const user = {};
Reflect.set(user, "name", "Joe");
console.log(Reflect.get(user, "name")); // Joe
console.log(Reflect.has(user, "name")); // true

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

A:

  • == checks for equality after type coercion.

  • === checks for strict equality without type coercion.

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

29. Implement a Custom Promise.race Method.

A:

function customPromiseRace(promises) {
  return new Promise((resolve, reject) => {
    promises.forEach((promise) => {
      Promise.resolve(promise).then(resolve).catch(reject);
    });
  });
}

const p1 = new Promise((res) => setTimeout(res, 500, "First"));
const p2 = new Promise((res) => setTimeout(res, 300, "Second"));
customPromiseRace([p1, p2]).then(console.log); // Second

30. Explain the Observer Pattern. Implement It.

A: The Observer Pattern allows objects (observers) to watch and react to changes in another object (subject).

class Subject {
  constructor() {
    this.observers = [];
  }

  addObserver(observer) {
    this.observers.push(observer);
  }

  removeObserver(observer) {
    this.observers = this.observers.filter((obs) => obs !== observer);
  }

  notify(data) {
    this.observers.forEach((observer) => observer.update(data));
  }
}

class Observer {
  update(data) {
    console.log(`Observer received data: ${data}`);
  }
}

const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();

subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notify("Hello Observers!"); // Both observers receive the update

31. Explain Set and Map. When Should You Use Them?

A:

  • Set: A collection of unique values.

  • Map: A collection of key-value pairs.

const set = new Set([1, 2, 2, 3]);
console.log(set); // Set { 1, 2, 3 }

const map = new Map();
map.set("name", "Joe");
console.log(map.get("name")); // Joe

32. What Are Optional Chaining and Nullish Coalescing?

A:

  • Optional Chaining (?.) prevents errors when accessing properties of null or undefined.

  • Nullish Coalescing (??) provides a default value when a value is null or undefined.

const user = { name: "Joe" };
console.log(user?.address?.city); // undefined (safe access)

const value = null;
console.log(value ?? "default"); // "default"

33. Implement a Custom Flatten Function for Nested Arrays.

A:

function flatten(arr) {
  return arr.reduce(
    (acc, val) => acc.concat(Array.isArray(val) ? flatten(val) : val),
    []
  );
}

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

34. What Are Tagged Templates?

A: Tagged templates process template literals with a custom function.

function tag(strings, ...values) {
  return strings.reduce(
    (result, str, i) => `${result}${str}${values[i] || ""}`,
    ""
  );
}

const name = "Joe";
console.log(tag`Hello, ${name}!`); // Hello, Joe!

35. Explain Object.create and Its Use Cases.

A: Object.create creates a new object with the specified prototype.

const parent = { greet() { console.log("Hello"); } };
const child = Object.create(parent);
child.greet(); // Hello

36. What Are Generators in JavaScript?

A: Generators allow functions to yield multiple values over time.

function* counter() {
  yield 1;
  yield 2;
  yield 3;
}

const gen = counter();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

37. What Is the Purpose of Symbol.iterator?

A: It customizes the iteration behavior of objects.

const iterable = {
  [Symbol.iterator]() {
    let i = 0;
    return {
      next() {
        return i < 3 ? { value: i++, done: false } : { done: true };
      },
    };
  },
};

for (const val of iterable) {
  console.log(val); // 0, 1, 2
}

38. What Is Hoisting?

A: Hoisting moves variable and function declarations to the top of their scope.

console.log(a); // undefined (hoisted declaration)
var a = 5;

39. What Are JavaScript Modules?

A: Modules enable code reuse and better organization.

// math.js
export function add(a, b) { return a + b; }

// main.js
import { add } from "./math.js";
console.log(add(2, 3)); // 5

40. What Is the Purpose of Object.seal?

A: Object.seal prevents adding or removing properties from an object.

const obj = { a: 1 };
Object.seal(obj);
obj.b = 2; // Not allowed
console.log(obj); // { a: 1 }

Conclusion

The above 100 code snippets, coupled with consistent practice and revision, can significantly improve your logical understanding and problem-solving skills in JavaScript. By focusing on real-world tasks and exploring diverse scenarios, you can develop a strong foundation in the language's core concepts and advanced features.

JavaScript’s ability to handle everything from simple interactions to complex applications makes it an essential skill for any developer. Each snippet serves as a stepping stone, helping you gain confidence in areas like DOM manipulation, asynchronous programming, ES6+ features, and more.

Remember, mastery comes with persistence. Keep experimenting, revisiting concepts, and building on what you’ve learned. With dedication, you’ll not only enhance your JavaScript skills but also unlock the potential to create dynamic, robust, and scalable applications.

Did you find this article valuable?

Support CodeWords by becoming a sponsor. Any amount is appreciated!