JavaScript Interview Questions

 

Beginner Level

  1. What is JavaScript?

    • Answer: JavaScript is a lightweight, interpreted programming language primarily used for creating dynamic web pages. It is client-side, but can also be used on the server-side with environments like Node.js.

  2. What are the data types in JavaScript?

    • Answer: JavaScript has the following data types:

      • Primitive: String, Number, Boolean, Null, Undefined, Symbol, BigInt

      • Non-primitive: Object, Array, Function

  3. What is var, let, and const?

    • Answer:

      • var: Function-scoped, can be redeclared and reassigned.

      • let: Block-scoped, cannot be redeclared, but can be reassigned.

      • const: Block-scoped, cannot be redeclared or reassigned (although object properties can be modified).

  4. What is hoisting in JavaScript?

    • Answer: Hoisting is JavaScript's default behavior of moving declarations (variables and functions) to the top of their containing scope before code execution. var variables are hoisted and initialized with undefined, while let and const are hoisted but not initialized.

  5. What is a closure?

    • Answer: A closure is a function that remembers and accesses variables from its lexical scope, even when the function is executed outside that scope.

  6. What are arrow functions in JavaScript?

    • Answer: Arrow functions provide a shorter syntax for writing functions. They don’t bind their own this, making them ideal for non-method functions.
      const sum = (a, b) => a + b;

Intermediate Level

  1. Explain the difference between == and ===.

    • Answer:

      • == checks for equality after performing type coercion.

      • === checks for equality without type coercion, ensuring both type and value are the same.


2 == "2"  // true

2 === "2" // false


  1. What is event delegation?

    • Answer: Event delegation is a technique where a single event listener is added to a parent element, and it handles events triggered by its child elements. It takes advantage of event bubbling.

  2. What is the difference between null and undefined?

    • Answer:

      • undefined means a variable has been declared but has not yet been assigned a value.

      • null is an assignment value, representing the intentional absence of an object value.

  3. What is the this keyword in JavaScript?

    • Answer: this refers to the context in which the function is called. Its value depends on how the function is invoked:

      • In global scope, this refers to the global object.

      • In an object method, this refers to the object itself.

      • In event handlers or callback functions, this can vary.

  4. What is the map(), filter(), and reduce() function in JavaScript?

    • Answer:

      • map(): Returns a new array with the results of calling a provided function on every element in the calling array.

      • filter(): Returns a new array with elements that pass the test implemented by the provided function.

      • reduce(): Executes a reducer function on each element of the array, resulting in a single output value.


const numbers = [1, 2, 3, 4];

const doubled = numbers.map(n => n * 2);  // [2, 4, 6, 8]

const even = numbers.filter(n => n % 2 === 0); // [2, 4]

const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 10


  1. What are Promises in JavaScript?

    • Answer: A Promise is an object representing the eventual completion or failure of an asynchronous operation. It can be in one of three states: pending, fulfilled, or rejected.


const promise = new Promise((resolve, reject) => {

  // async work

  if (success) {

    resolve("Success!");

  } else {

    reject("Error!");

  }

});


Advanced Level

  1. What is the event loop in JavaScript?

    • Answer: The event loop is a mechanism that allows JavaScript to perform non-blocking, asynchronous operations by handling callbacks and promises. It continuously checks the call stack and the callback queue. When the call stack is empty, it processes callbacks from the queue.

  2. What is debouncing and throttling in JavaScript?

    • Answer:

      • Debouncing: Ensures a function is called after a specified delay only once, and prevents it from being called again during that time if invoked repeatedly.

      • Throttling: Ensures a function is called at most once in a specified time period, no matter how often it’s invoked.


// Debounce

function debounce(fn, delay) {

  let timer;

  return function() {

    clearTimeout(timer);

    timer = setTimeout(fn, delay);

  };

}


// Throttle

function throttle(fn, limit) {

  let lastCall = 0;

  return function() {

    const now = new Date().getTime();

    if (now - lastCall >= limit) {

      lastCall = now;

      fn();

    }

  };

}


  1. What are generators in JavaScript?

    • Answer: Generators are functions that can be paused and resumed during execution, allowing you to manage async flow more easily. They return an iterator object.

javascript
CopyEdit
function* generatorFunction() {

  yield 'First';

  yield 'Second';

}

const generator = generatorFunction();

console.log(generator.next()); // { value: 'First', done: false }

console.log(generator.next()); // { value: 'Second', done: false }

console.log(generator.next()); // { value: undefined, done: true }


  1. What is memoization?

    • Answer: Memoization is a performance optimization technique where the results of expensive function calls are cached and returned when the same inputs occur again.


function memoize(fn) {

  const cache = {};

  return function(...args) {

    const key = JSON.stringify(args);

    if (cache[key]) {

      return cache[key];

    }

    const result = fn(...args);

    cache[key] = result;

    return result;

  };

}


  1. What is the difference between call(), apply(), and bind()?

    • Answer:

      • call(): Invokes a function with a specified this context and individual arguments.

      • apply(): Similar to call(), but accepts an array of arguments.

      • bind(): Returns a new function that, when invoked, has its this context set to the provided value.

Beginner Level

  1. What are the different ways to create an object in JavaScript?

    • Answer: You can create an object in several ways:

Using object literal:

const obj = { key: 'value' };


Using new Object():
javascript
CopyEdit
const obj = new Object();


Using constructor functions:

function Person(name) {

  this.name = name;

}

const person = new Person('John');


Using ES6 class:

class Person {

  constructor(name) {

    this.name = name;

  }

}

const person = new Person('John');


  1. What is the difference between forEach and map?

    • Answer:

      • forEach: Iterates over an array and executes a provided function for each element but does not return a new array.

      • map: Iterates over an array, executes a function, and returns a new array with the results.


const arr = [1, 2, 3];

arr.forEach(num => console.log(num * 2)); // Output: 2, 4, 6

const mappedArr = arr.map(num => num * 2); // Output: [2, 4, 6]


  1. What are template literals in JavaScript?

    • Answer: Template literals (introduced in ES6) allow you to embed expressions inside string literals using backticks (`) and ${} for interpolation.


const name = 'Alice';

const greeting = `Hello, ${name}!`;  // "Hello, Alice!"



Intermediate Level

  1. What is a callback function?

    • Answer: A callback function is a function passed as an argument to another function, which is then invoked inside the outer function to complete some kind of routine or action.


function greet(name, callback) {

  console.log(`Hello, ${name}`);

  callback();

}

greet('Alice', function() {

  console.log('This is a callback function.');

});


  1. Explain async/await in JavaScript.

    • Answer: async/await is a modern syntax for writing asynchronous code. An async function returns a Promise, and await pauses the execution of the function until the Promise is resolved.


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();


  1. What are higher-order functions in JavaScript?

    • Answer: Higher-order functions are functions that take other functions as arguments or return a function as a result. Examples include map(), filter(), and reduce().


function higherOrderFunction(fn) {

  return function(value) {

    return fn(value);

  };

}

const double = higherOrderFunction(n => n * 2);

console.log(double(5)); // Output: 10


  1. Explain the spread and rest operators.

    • Answer:

      • Spread operator (...): Expands an array or object into individual elements.

      • Rest operator (...): Collects multiple elements or arguments into a single array.


// Spread operator

const arr1 = [1, 2];

const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]


// Rest operator

function sum(...numbers) {

  return numbers.reduce((acc, curr) => acc + curr, 0);

}

console.log(sum(1, 2, 3)); // Output: 6


  1. What is destructuring in JavaScript?

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

javascript
CopyEdit
const [a, b] = [1, 2];  // a = 1, b = 2

const { name, age } = { name: 'Alice', age: 25 }; // name = 'Alice', age = 25



Advanced Level

  1. Explain the concept of Prototypes in JavaScript.

    • Answer: Every JavaScript object has a prototype, which is another object it inherits properties and methods from. This is the basis of prototypal inheritance. You can add properties or methods to the prototype to share them across all instances of an object.

javascript
CopyEdit
function Person(name) {

  this.name = name;

}

Person.prototype.greet = function() {

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

};

const john = new Person('John');

john.greet(); // "Hello, my name is John"


  1. What is the difference between shallow copy and deep copy?

    • Answer:

      • Shallow Copy: Copies the reference of an object (so nested objects are still referenced by both the original and copied objects).

      • Deep Copy: Creates a new object entirely, including nested objects, so changes to one object do not affect the other.


// Shallow Copy

const obj1 = { a: 1, b: { c: 2 } };

const obj2 = { ...obj1 };

obj2.b.c = 3;  // Affects obj1.b.c


// Deep Copy (using JSON methods as an example)

const obj3 = JSON.parse(JSON.stringify(obj1));

obj3.b.c = 4;  // Does not affect obj1.b.c


  1. What are Web Workers in JavaScript?

    • Answer: Web Workers allow you to run JavaScript code in the background, independent of the user interface, which helps prevent blocking the main thread during long-running tasks.


// Create a worker.js file with:

// self.addEventListener('message', function(e) { postMessage(e.data * 2); });


const worker = new Worker('worker.js');

worker.postMessage(5);  // Sends message to worker

worker.onmessage = function(event) {

  console.log(event.data);  // Output: 10 (result from worker)

};


  1. What are JavaScript modules and how are they used?

    • Answer: JavaScript modules allow you to split code into separate files, and each file can export values (like functions, variables, or classes) which can be imported and used in other files. This helps organize and maintain code better.


// Exporting in module.js

export const greeting = 'Hello';

export function greet(name) {

  console.log(`${greeting}, ${name}`);

}


// Importing in another file

import { greeting, greet } from './module.js';

greet('Alice'); // "Hello, Alice"


  1. What is the difference between synchronous and asynchronous JavaScript?

    • Answer:

      • Synchronous JavaScript: Code is executed line by line. If one operation takes a long time, it blocks the next one from running.

      • Asynchronous JavaScript: Code execution doesn’t block the subsequent operations. Tasks like fetching data from an API can run in the background while other operations continue.


// Synchronous

const result = fetchData();  // Blocks until fetchData completes


// Asynchronous

fetchDataAsync().then(data => console.log(data));  // Continues to run other code


  1. Explain the concept of Currying in JavaScript.

    • Answer: Currying is the process of transforming a function that takes multiple arguments into a series of functions, each taking a single argument.


function add(a) {

  return function(b) {

    return a + b;

  };

}

const addFive = add(5);

console.log(addFive(3));  // Output: 8



1. What is event delegation and how does it work?

  • Answer: Event delegation is a technique in JavaScript where you attach a single event listener to a parent element instead of adding multiple event listeners to child elements. The event listener utilizes event bubbling to handle events triggered by child elements.

javascript

CopyEdit

document.getElementById('parent').addEventListener('click', function(event) {

  if (event.target && event.target.nodeName === 'BUTTON') {

    console.log('Button clicked:', event.target.textContent);

  }

});


  • How it works:

    1. An event is triggered on a child element.

    2. The event bubbles up to the parent.

    3. The parent’s event listener handles the event.

Advantages:

  • Fewer event listeners = better performance.

  • Dynamically added elements can be handled by the parent listener.


2. Explain the event loop and how JavaScript handles asynchronous code.

  • Answer: JavaScript uses an event-driven, non-blocking, single-threaded model for handling asynchronous operations. The event loop plays a central role in this process.

    • The call stack holds the currently executing code.

    • The task queue holds the asynchronous tasks (like setTimeout callbacks, Promises, etc.).

    • The event loop checks the call stack, and if it’s empty, it pushes tasks from the task queue onto the call stack.

Example:

javascript

CopyEdit

console.log('Start');

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

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

console.log('End');


// Output:

// Start

// End

// Promise

// Timeout


Why this happens:

  • The synchronous code is executed first.

  • Microtasks (like Promises) are prioritized over macrotasks (like setTimeout).


3. What is memory leak in JavaScript, and how can it be avoided?

  • Answer: A memory leak occurs when a program allocates memory but never releases it, leading to excessive memory consumption. In JavaScript, memory is managed by the garbage collector, but certain patterns can prevent garbage collection, leading to memory leaks.

Common causes:

  1. Global variables: Unintentionally creating global variables can cause them to persist longer than needed.

  2. Event listeners: Forgetting to remove event listeners can prevent objects from being garbage-collected.

  3. Closures: Capturing variables in closures that persist beyond their intended lifecycle.

  4. Detached DOM elements: If DOM elements are removed but JavaScript references to them still exist, they won’t be garbage collected.

Prevention techniques:

  • Avoid global variables.

  • Remove event listeners when no longer needed.

  • Manage references inside closures carefully.

  • Set references to null when you no longer need objects.


4. What is this in JavaScript, and how does it behave in different contexts?

  • Answer: The value of this refers to the object that is executing the current function. The value of this can vary based on the execution context.

Examples:

Global context: In non-strict mode, this refers to the global object (window in browsers). In strict mode, this is undefined.

javascript
CopyEdit
console.log(this);  // window (in non-strict mode)


Object method: Inside a method, this refers to the object the method belongs to.

javascript
CopyEdit
const obj = {

  name: 'Alice',

  greet() {

    console.log(this.name);  // 'Alice'

  }

};


Constructor function: In a constructor, this refers to the newly created object.

javascript
CopyEdit
function Person(name) {

  this.name = name;

}

const john = new Person('John');


Arrow functions: this in arrow functions is lexically bound to the surrounding context.

javascript
CopyEdit
const obj = {

  name: 'Alice',

  greet: () => console.log(this.name)  // 'undefined', because `this` is bound to the outer scope.

};



5. What are generators in JavaScript and how are they used?

  • Answer: Generators are special functions that can be paused and resumed. They use the function* syntax and yield to return multiple values at different points in time.

Example:

javascript

CopyEdit

function* numberGenerator() {

  yield 1;

  yield 2;

  yield 3;

}

const generator = numberGenerator();

console.log(generator.next());  // { value: 1, done: false }

console.log(generator.next());  // { value: 2, done: false }

console.log(generator.next());  // { value: 3, done: false }

console.log(generator.next());  // { value: undefined, done: true }


Key points:

  • The yield keyword pauses the generator function and returns a value.

  • next() resumes the generator function’s execution and returns an object with { value, done }.


6. What are Promises and how do they work?

  • Answer: A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation. Promises have three states:

    1. Pending: The initial state, neither fulfilled nor rejected.

    2. Fulfilled: The operation completed successfully.

    3. Rejected: The operation failed.

Example:

javascript

CopyEdit

const promise = new Promise((resolve, reject) => {

  const success = true;

  if (success) {

    resolve('Success!');

  } else {

    reject('Failure!');

  }

});


promise.then((message) => {

  console.log(message);  // 'Success!'

}).catch((error) => {

  console.error(error);

});


  • then() handles the fulfillment of the Promise.

  • catch() handles the rejection of the Promise.


7. What is the difference between call(), apply(), and bind() in JavaScript?

  • Answer:

    • call(): Invokes a function with a specified this value and arguments passed individually.

javascript
CopyEdit
function greet(greeting) {

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

}

const person = { name: 'Alice' };

greet.call(person, 'Hello');  // Output: "Hello, Alice"


    • apply(): Similar to call(), but arguments are passed as an array.

javascript
CopyEdit
greet.apply(person, ['Hello']);  // Output: "Hello, Alice"


    • bind(): Returns a new function with a specified this value and optionally prepends arguments.

javascript
CopyEdit
const boundGreet = greet.bind(person, 'Hello');

boundGreet();  // Output: "Hello, Alice"



8. Explain what a closure is and give an example.

  • Answer: A closure is a function that retains access to variables from its outer scope even after the outer function has returned.

Example:

javascript

CopyEdit

function outerFunction() {

  let outerVar = 'I am from the outer function';

  return function innerFunction() {

    console.log(outerVar);  // Closure: retains access to outerVar

  };

}

const inner = outerFunction();

inner();  // Output: 'I am from the outer function'


Key points:

  • Closures help maintain state and allow for data encapsulation.

  • They are used in scenarios like data hiding, currying, and partial application.


9. What are WeakMap and WeakSet in JavaScript?

  • Answer: WeakMap and WeakSet are collections that allow garbage collection of their keys when there are no other references to those keys.

WeakMap:

  • A WeakMap holds key-value pairs where keys are objects, and the references to those keys are weak.

  • If the only remaining reference to an object is as a key in a WeakMap, the object can be garbage collected.

WeakSet:

  • A WeakSet is a collection of objects, and just like WeakMap, the references to the objects are weak.

javascript

CopyEdit

let obj = { name: 'Alice' };

const weakMap = new WeakMap();

weakMap.set(obj, 'value');

obj = null;  // The object will be garbage collected, no memory leak.


Advantages:

  • Helps prevent memory leaks as objects in a WeakMap or WeakSet are automatically garbage-collected when there are no other references to them.


10. What is the difference between == and === in JavaScript?

Answer: The == operator performs type coercion, meaning it converts the types of the values being compared to the same type before making the comparison.
javascript
CopyEdit
5 == '5';  // true


The === operator (strict equality) does not perform type coercion. Both the value and the type must be the same. javascript 5 === '5'; // false      


1. What is the difference between synchronous and asynchronous programming in JavaScript?

  • Answer:

    • Synchronous programming: Code is executed line by line in the order it appears. Each statement must complete before the next one is executed.

    • Asynchronous programming: Code is executed without waiting for other code to finish. This allows the program to continue running while other operations (such as API calls, timers, or file reading) are happening in the background.

Example:

javascript

CopyEdit

console.log('Start');

setTimeout(() => {

  console.log('Asynchronous operation');

}, 1000);

console.log('End');


// Output:

// Start

// End

// Asynchronous operation (after 1 second)


In the example, setTimeout is asynchronous and doesn't block the execution of the next statement.


2. What are JavaScript proxies, and what are they used for?

  • Answer: A Proxy is an object that wraps another object and intercepts operations (like reading, writing, or function invocation) performed on that object. Proxies allow you to customize and redefine fundamental operations on objects.

Example:

javascript

CopyEdit

const target = {

  message: 'Hello World'

};


const handler = {

  get: function(obj, prop) {

    return prop in obj ? obj[prop] : 'Property does not exist';

  }

};


const proxy = new Proxy(target, handler);

console.log(proxy.message);  // Output: 'Hello World'

console.log(proxy.nonExistent);  // Output: 'Property does not exist'


Use cases:

  • Validation: Enforce rules before modifying an object.

  • Data binding: Monitor changes in objects for UI frameworks.

  • API control: Custom behavior for API wrappers.


3. What is the Reflect API in JavaScript? How does it relate to Proxies?

  • Answer: The Reflect API is a built-in object that provides methods for interceptable JavaScript operations. It has the same methods as handler traps in Proxies and allows you to perform default operations that proxies might override.

Example:

javascript

CopyEdit

const target = {

  x: 42

};


const handler = {

  get: function(obj, prop) {

    console.log(`Property ${prop} was accessed`);

    return Reflect.get(...arguments);  // Default behavior using Reflect

  }

};


const proxy = new Proxy(target, handler);

console.log(proxy.x);  // Logs: "Property x was accessed" and then outputs 42


  • Relation to Proxies: While Proxies allow overriding object behaviors, Reflect enables using default behaviors within the proxy handlers. It provides methods like Reflect.get(), Reflect.set(), Reflect.deleteProperty(), etc.


4. What are the differences between null and undefined in JavaScript?

  • Answer:

    • null: Represents the intentional absence of any object value. It is a keyword and is explicitly assigned by the developer.

    • undefined: Means that a variable has been declared but has not yet been assigned a value.

Examples:

javascript

CopyEdit

let a;

console.log(a);  // Output: undefined (variable declared but not assigned)


let b = null;

console.log(b);  // Output: null (explicitly assigned)


Key differences:

  • null is an assigned value; undefined is the default for uninitialized variables.

  • typeof null is "object"; typeof undefined is "undefined".


5. What is the debounce function and why is it used?

  • Answer: Debouncing is a technique to limit the rate at which a function is executed. It ensures that a function is only invoked after a specified delay since the last time it was called.

Use case: Useful for scenarios like search input fields where you don't want the search function to trigger on every keystroke but only after the user stops typing.

Example:

javascript

CopyEdit

function debounce(func, delay) {

  let timeout;

  return function() {

    const context = this;

    const args = arguments;

    clearTimeout(timeout);

    timeout = setTimeout(() => func.apply(context, args), delay);

  };

}


function handleSearchInput() {

  console.log('Search triggered');

}


const debouncedSearch = debounce(handleSearchInput, 300);

// Now the function `debouncedSearch` will only execute 300ms after the last call.



6. What is throttling, and how is it different from debouncing?

  • Answer: Throttling ensures that a function is only executed once every specified interval, even if it is called multiple times within that interval.

Use case: Useful for controlling execution of code triggered by user actions like scrolling or window resizing, where constant execution could cause performance issues.

Example:

javascript

CopyEdit

function throttle(func, limit) {

  let lastFunc;

  let lastRan;

  return function() {

    const context = this;

    const args = arguments;

    if (!lastRan) {

      func.apply(context, args);

      lastRan = Date.now();

    } else {

      clearTimeout(lastFunc);

      lastFunc = setTimeout(() => {

        if (Date.now() - lastRan >= limit) {

          func.apply(context, args);

          lastRan = Date.now();

        }

      }, limit - (Date.now() - lastRan));

    }

  };

}


function handleScroll() {

  console.log('Scroll event triggered');

}


const throttledScroll = throttle(handleScroll, 1000);


Difference between Debouncing and Throttling:

  • Debouncing: Function executes only after the specified delay has passed without further calls.

  • Throttling: Function executes at most once per specified interval, regardless of how many times it’s called.


7. What are JavaScript modules, and how do import and export work?

  • Answer: JavaScript modules allow you to break up your code into separate files and use import/export syntax to share code between these files.

  • export: Exports variables, functions, or classes so they can be imported in other modules.

  • import: Imports the exported code from another module.

Example:

javascript

CopyEdit

// module.js

export const greet = () => {

  console.log('Hello from module');

};


export const name = 'John';


// main.js

import { greet, name } from './module.js';

greet();  // Output: 'Hello from module'

console.log(name);  // Output: 'John'


Types of exports:

  • Named export: You can export multiple variables or functions, and you must import them by name.

  • Default export: Only one default export is allowed per module, and it can be imported with any name.

Example of default export:

javascript

CopyEdit

// module.js

export default function() {

  console.log('Default export');

}


// main.js

import myFunction from './module.js';

myFunction();  // Output: 'Default export'



8. What is hoisting in JavaScript, and how does it affect variables and functions?

  • Answer: Hoisting is JavaScript's default behavior of moving variable and function declarations to the top of their containing scope (global or function) before code execution.

Function hoisting:

javascript

CopyEdit

greet();  // Output: 'Hello'

function greet() {

  console.log('Hello');

}


Variable hoisting:

javascript

CopyEdit

console.log(x);  // Output: undefined

var x = 5;


  • In the case of var declarations, the variable is hoisted but not initialized, so it results in undefined.

  • let and const also get hoisted but are not initialized until the line where they are declared (i.e., they exist in a "temporal dead zone" before the declaration).


9. What is tail call optimization, and does JavaScript support it?

  • Answer: Tail call optimization (TCO) is a feature in which the last action of a function is to return the result of another function, allowing the engine to optimize the call stack and prevent stack overflow errors.

Example:

javascript

CopyEdit

function factorial(n, acc = 1) {

  if (n === 1) return acc;

  return factorial(n - 1, n * acc);  // Tail call

}


factorial(10000);  // Won't cause stack overflow with TCO


  • JavaScript support for TCO: TCO is supported in modern JavaScript (ES6) environments, but only in strict mode and not in all engines.


10. What are async iterators, and how are they used?

  • Answer: Async iterators are objects that conform to the async iterable protocol, which allows you to use for await...of loops to iterate over asynchronous data streams.

Example:

javascript

CopyEdit

async function* fetchData() {

  yield await fetch('https://api.example.com/data/1');

  yield await fetch('https://api.example.com/data/2');

}


(async () => {

  for await (const data of fetchData()) {

    console.log(await data.json());

  }

})();


  • fetchData is an asynchronous generator that can yield Promises that are awaited inside a for await...of loop.


Post a Comment

Previous Post Next Post