JavaScript Interview Questions and Answers


What is JavaScript?

JavaScript is a high-level, interpreted, and dynamic programming language primarily used for front-end web development. It enables interactive web pages and is now widely used for back-end development (Node.js), mobile apps, and more.

What are the data types in JavaScript?

JavaScript has eight data types:

  • Primitive types:
    • `string`
    • `number`
    • `boolean`
    • `null`
    • `undefined`
    • `symbol` (ES6)
    • `bigint` (ES2020)
  • Non-primitive type:
    • `object`
Explain the difference between `null` and `undefined`.
  • `undefined`: A variable that has been declared but has not been assigned a value. It's the default value for uninitialized variables and function parameters that are not passed.
  • `null`: Represents the intentional absence of any object value. It is an assignment value, meaning you can assign `null` to a variable.
  •             
    let x; // x is undefined
    let y = null; // y is null
        
        
What is the difference between `==` and `===` operators?
  • `==` (Equality operator): Compares two values for equality after performing type coercion (converting the types to match if possible).
  • `===` (Strict equality operator): Compares two values for equality without performing type coercion. The values must be of the same type to be considered equal.
  •             
    console.log(5 == '5'); // true (type coercion)
    console.log(5 === '5'); // false (different types)
        
        
What is the scope of a variable in JavaScript?

Scope determines the accessibility of variables, functions, and objects in some particular part of your code. JavaScript has:

  • Global Scope: Variables declared outside of any function or block are in global scope and are accessible from anywhere in the code.
  • Function Scope: Variables declared inside a function are in function scope and are only accessible within that function.
  • Block Scope (ES6+): Variables declared with `let` and `const` inside a block (defined by curly braces `{}`) are in block scope and are only accessible within that block.
Explain Hoisting in JavaScript.

Hoisting is a JavaScript mechanism where variable and function declarations are moved to the top of their containing scope during the compilation phase, *before* the code is executed. However, only the *declarations* are hoisted, not the *initializations*. `let` and `const` are also hoisted, but they are in a "Temporal Dead Zone" until their declaration is reached, preventing access before initialization.

        
console.log(myVar); // undefined (declaration is hoisted)
var myVar = 10;

// console.log(myLet); // ReferenceError: Cannot access 'myLet' before initialization (Temporal Dead Zone)
// let myLet = 20;

myFunction(); // "Hello" (function declaration is hoisted)
function myFunction() {
  console.log("Hello");
}
    
    
What is the difference between `var`, `let`, and `const`?
  • `var`: Function-scoped, can be redeclared and reassigned. Subject to hoisting issues. (Older way of declaring variables).
  • `let`: Block-scoped, can be reassigned but not redeclared within the same scope. Solves hoisting issues (Temporal Dead Zone). (Recommended for variables that will change).
  • `const`: Block-scoped, cannot be redeclared or reassigned. Must be initialized at declaration. (Recommended for variables that should not change). Note: For objects/arrays, the reference is constant, but the contents can be modified.
What is a Closure?

A closure is the combination of a function and the lexical environment within which that function was declared. It allows a function to access variables from its outer (enclosing) scope, even after the outer function has finished executing.

        
function outerFunction() {
  let outerVariable = 'I am from outer function';

  function innerFunction() {
    console.log(outerVariable); // Accessing outerVariable
  }

  return innerFunction;
}

const myClosure = outerFunction();
myClosure(); // Output: "I am from outer function"
    
    
Explain the concept of `this` in JavaScript.

`this` refers to the context in which a function is executed. Its value depends on how the function is called:

  • Global context: In the global scope, `this` refers to the global object (e.g., `window` in browsers, `global` in Node.js).
  • Method call: If a function is called as a method of an object (`obj.method()`), `this` refers to the object (`obj`).
  • Function call (simple): In a regular function call (not a method or constructor), `this` refers to the global object in non-strict mode. In strict mode, `this` is `undefined`.
  • Constructor call: When a function is called with `new` (`new MyConstructor()`), `this` refers to the newly created instance of the object.
  • Explicit binding: Using `call()`, `apply()`, or `bind()`, you can explicitly set the value of `this`.
  • Arrow functions: Arrow functions do not have their own `this`. They inherit `this` from the enclosing lexical context.
What is the difference between `call`, `apply`, and `bind`?

These methods are used to set the value of `this` for a function and to call the function.

  • `call(thisArg, arg1, arg2, ...)`: Calls the function immediately with the specified `this` value and arguments passed individually.
  • `apply(thisArg, [argsArray])`: Calls the function immediately with the specified `this` value and arguments passed as an array.
  • `bind(thisArg, arg1, arg2, ...)`: Returns a *new* function with the specified `this` value bound. It does not call the function immediately.
        
const person = { name: 'Alice' };

function greet(greeting, punctuation) {
  console.log(greeting + ', ' + this.name + punctuation);
}

greet.call(person, 'Hello', '!'); // Output: "Hello, Alice!"
greet.apply(person, ['Hi', '.']); // Output: "Hi, Alice."

const boundGreet = greet.bind(person, 'Hey');
boundGreet('?'); // Output: "Hey, Alice?"
    
    
What is the difference between Function Declaration and Function Expression?
  • Function Declaration: Functions declared using the `function` keyword followed by a name. They are hoisted to the top of their scope, so you can call them before they are defined in the code.
                    
    myDeclaration(); // Works due to hoisting
    function myDeclaration() { console.log("Declaration"); }
        
        
  • Function Expression: Functions assigned to a variable. They are not hoisted in the same way; the variable declaration is hoisted, but the function assignment is not. You must define the function expression before calling it.
                    
    // myExpression(); // Error: myExpression is not a function (at this point)
    const myExpression = function() { console.log("Expression"); };
    myExpression(); // Works
        
        
What is an Arrow Function? What are its benefits?

Arrow functions (ES6) provide a shorter syntax for writing function expressions. Key benefits:

  • Concise syntax.
  • Lexical `this` binding: They do not have their own `this` binding; `this` is inherited from the enclosing scope. This solves common issues with `this` in callbacks.
  • No `arguments` object: They do not have their own `arguments` object. You can use rest parameters (`...args`) instead.
        
const add = (a, b) => a + b;

// Example of lexical this:
class MyClass {
  value = 10;
  oldMethod() {
    setTimeout(function() {
      console.log(this.value); // 'this' is window or undefined in strict mode
    }, 100);
  }
  arrowMethod() {
    setTimeout(() => {
      console.log(this.value); // 'this' is MyClass instance (lexical)
    }, 100);
  }
}
    
    
What is the Event Loop in JavaScript?

The Event Loop is a fundamental mechanism in JavaScript (especially in browsers and Node.js) that handles asynchronous operations. It continuously checks if the call stack is empty and if there are any tasks in the task queue (or microtask queue) that are ready to be executed. If the call stack is empty, tasks from the queue are moved to the stack for execution.

Explain the difference between Synchronous and Asynchronous code.
  • Synchronous: Code that executes sequentially, one line after another. Each operation must complete before the next one starts. This can block the main thread.
  • Asynchronous: Code that allows other operations to run while waiting for a long-running task (like fetching data or reading a file) to complete. It doesn't block the main thread and uses mechanisms like callbacks, Promises, or `async`/`await`.
What are Promises? How do they work?

Promises are objects representing the eventual completion (or failure) of an asynchronous operation and its resulting value. A Promise can be in one of three states:

  • `pending`: Initial state, neither fulfilled nor rejected.
  • `fulfilled`: The operation completed successfully, and the promise has a resulting value.
  • `rejected`: The operation failed, and the promise has a reason for the failure (an error).

Promises have methods like `.then()` (for handling fulfillment and optional rejection) and `.catch()` (for handling rejection).

        
const myPromise = new Promise((resolve, reject) => {
  // Asynchronous operation
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve("Operation successful!");
    } else {
      reject("Operation failed!");
    }
  }, 1000);
});

myPromise
  .then(result => {
    console.log(result); // Output: "Operation successful!"
  })
  .catch(error => {
    console.error(error); // Output: "Operation failed!"
  });
    
    
What is `async`/`await`?

`async`/`await` is syntactic sugar built on top of Promises, making asynchronous code look and behave a little more like synchronous code. An `async` function always returns a Promise. The `await` keyword can only be used inside an `async` function and pauses the execution of the `async` function until the awaited Promise settles (fulfills or rejects).

        
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 fetching data:', error);
  }
}

fetchData();
    
    
What is the DOM?

The Document Object Model (DOM) is a programming interface for web documents. It represents the structure of a web page as a tree of objects, allowing JavaScript to access and manipulate the content, structure, and style of the page.

How do you select elements in the DOM?
  • `document.getElementById('id')`: Selects a single element by its ID.
  • `document.querySelector('selector')`: Selects the first element that matches a CSS selector.
  • `document.querySelectorAll('selector')`: Selects all elements that match a CSS selector, returning a NodeList.
  • `document.getElementsByClassName('className')`: Selects elements by their class name, returning an HTMLCollection.
  • `document.getElementsByTagName('tagName')`: Selects elements by their tag name, returning an HTMLCollection.
How do you add and remove event listeners?
  • `element.addEventListener(event, handler, options)`: Attaches an event handler function to an element for a specific event.
  • `element.removeEventListener(event, handler, options)`: Removes an event handler that was previously attached with `addEventListener`.
        
const button = document.getElementById('myButton');

function handleClick() {
  alert('Button clicked!');
}

button.addEventListener('click', handleClick);

// To remove later:
// button.removeEventListener('click', handleClick);
    
    
What is Event Bubbling and Event Capturing?
  • Event Bubbling: When an event occurs on an element, it first runs the handlers on that element, then on its parent, then on its grandparent, and so on, up the DOM tree. This is the default phase.
  • Event Capturing: The opposite of bubbling. The event is first captured by the outermost element and propagates inwards to the target element. This phase happens before bubbling. You can enable capturing by passing `true` as the third argument to `addEventListener`.
What is Event Delegation?

Event delegation is a technique where you attach a single event listener to a parent element instead of attaching multiple listeners to individual child elements. When an event occurs on a child, it bubbles up to the parent, and the parent's listener handles the event. This is efficient for performance, especially with a large number of child elements.

What is the difference between `localStorage` and `sessionStorage`?

Both are web storage APIs for storing data key-value pairs in the browser, but they differ in their scope and lifetime:

  • `localStorage`: Stores data with no expiration date. The data persists until explicitly cleared by the user or script. Data is available across browser windows with the same origin.
  • `sessionStorage`: Stores data for the duration of a single browser session. The data is cleared when the browser tab or window is closed. Data is isolated to the tab/window that created it.
What are Cookies?

Cookies are small pieces of data stored by a website on a user's browser. They are primarily used for:

  • Session management (keeping users logged in).
  • Personalization (remembering user preferences).
  • Tracking (user behavior and advertising).

Cookies have limitations in size and are sent with every HTTP request to the server, which can impact performance. Web storage (`localStorage`, `sessionStorage`) is generally preferred for client-side data storage.

What is JSON?

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write and easy for machines to parse and generate. It is based on a subset of the JavaScript programming language. JSON is commonly used for transmitting data between a server and a web application.

        
// JSON example
{
  "name": "John Doe",
  "age": 30,
  "isStudent": false,
  "courses": ["Math", "Science"]
}
    
    
How do you parse and stringify JSON?
  • `JSON.parse(jsonString)`: Converts a JSON string into a JavaScript object.
  • `JSON.stringify(javascriptObject)`: Converts a JavaScript object into a JSON string.
        
const jsonString = '{"name": "Alice", "age": 25}';
const jsObject = JSON.parse(jsonString);
console.log(jsObject.name); // Output: "Alice"

const anotherObject = { city: "New York", population: 8000000 };
const jsonOutput = JSON.stringify(anotherObject);
console.log(jsonOutput); // Output: '{"city":"New York","population":8000000}'
    
    
What is the difference between `let` and `const` when declaring objects/arrays?

When using `const` with objects or arrays, the *variable itself* cannot be reassigned to a *new* object or array. However, the *contents* of the object or array can still be modified.

        
const myObject = { a: 1 };
myObject.a = 2; // Valid: Modifying the object's property
console.log(myObject); // Output: { a: 2 }

// myObject = { b: 3 }; // Error: Cannot reassign a const variable

const myArray = [1, 2];
myArray.push(3); // Valid: Modifying the array's contents
console.log(myArray); // Output: [1, 2, 3]

// myArray = [4, 5]; // Error: Cannot reassign a const variable
    
    
Explain Prototype Inheritance.

Prototype inheritance is the mechanism in JavaScript where objects inherit properties and methods from other objects. Every JavaScript object has a prototype (except for the base `Object.prototype`), which is another object. When you try to access a property or method on an object, and it's not found on the object itself, JavaScript looks up the prototype chain until it finds the property or reaches the end of the chain.

What is the difference between `prototype` and `__proto__`?
  • `prototype`: A property on constructor functions/classes. It's the object that will be used as the prototype for instances created with that constructor/class.
  • `__proto__`: A property on instances of objects (though its direct use is discouraged, and `Object.getPrototypeOf()` is preferred). It's a reference to the prototype object that the instance inherits from.
        
function Person(name) {
  this.name = name;
}

Person.prototype.greet = function() {
  console.log("Hello, " + this.name);
};

const john = new Person("John");

console.log(john.__proto__ === Person.prototype); // true
john.greet(); // "Hello, John" (inherits from Person.prototype)
    
    
What is the difference between `map`, `filter`, and `reduce`?

These are common array methods that operate on arrays and return new arrays (except for `reduce`, which can return any value).

  • `map()`: Creates a new array by transforming each element of the original array using a provided function. The new array will have the same length as the original.
  • `filter()`: Creates a new array containing only the elements from the original array that pass a test provided by a function. The new array may be shorter than the original.
  • `reduce()`: Executes a reducer function on each element of the array, resulting in a single output value. It takes an accumulator and the current value and returns a new accumulator value for the next iteration.
        
const numbers = [1, 2, 3, 4];

const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8]
const evens = numbers.filter(num => num % 2 === 0); // [2, 4]
const sum = numbers.reduce((accumulator, num) => accumulator + num, 0); // 10
    
    
What is the difference between `for...in` and `for...of` loops?
  • `for...in`: Iterates over the *keys* (property names) of an object. It also iterates over inherited enumerable properties (unless filtered). Use with caution on arrays as it iterates over indices as strings.
  • `for...of` (ES6): Iterates over the *values* of iterable objects (like Arrays, Strings, Maps, Sets, NodeLists, etc.). It's the preferred way to iterate over array elements.
        
const obj = { a: 1, b: 2 };
for (const key in obj) {
  console.log(key); // "a", "b"
}

const arr = [10, 20];
for (const value of arr) {
  console.log(value); // 10, 20
}
    
    
What are Template Literals?

Template literals (ES6) are string literals allowing embedded expressions. They are enclosed by backticks (` `` `) and can contain placeholders (`${expression}`). They support multi-line strings without special characters.

        
const name = "World";
const greeting = `Hello, ${name}!
This is a multi-line string.`;
console.log(greeting);
    
    
What is Destructuring Assignment?

Destructuring assignment (ES6) is a syntax that allows you to unpack values from arrays or properties from objects into distinct variables.

        
// Array destructuring
const colors = ["red", "green", "blue"];
const [firstColor, secondColor] = colors;
console.log(firstColor); // "red"

// Object destructuring
const user = { id: 1, username: "john_doe" };
const { id, username } = user;
console.log(username); // "john_doe"
    
    
What are Spread Syntax and Rest Parameters?
  • Spread Syntax (`...`): Expands an iterable (like an array or string) into individual elements. Useful for creating copies of arrays/objects, concatenating arrays, or passing array elements as arguments to a function.
  • Rest Parameters (`...`): Collects multiple arguments into a single array. Used in function definitions to handle a variable number of arguments.
        
// Spread syntax
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]

const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 }; // { a: 1, b: 2 }

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

// Rest parameters
function logArgs(...args) {
  console.log(args); // args is an array
}
logArgs(1, 'hello', true); // [1, 'hello', true]
    
    
What are Modules in JavaScript?

Modules allow you to break down your code into smaller, reusable pieces, each in its own file. They help organize code, prevent naming conflicts, and manage dependencies. ES Modules (`import`/`export`) are the standard way to work with modules in modern JavaScript.

What is the difference between `export default` and `export`?
  • `export default`: Exports a single member as the default export from a module. It's imported without curly braces. There can only be one default export per module.
  • `export`: Exports named members from a module. They are imported using curly braces, matching the name used in the export. A module can have multiple named exports.
        
// module.js
export const namedExport = 10;
export function anotherNamedExport() {}
const myDefault = {};
export default myDefault;

// main.js
import myDefault, { namedExport, anotherNamedExport } from './module.js';
    
    
What is the purpose of the `use strict` directive?

The `'use strict';` directive enables strict mode in JavaScript. Strict mode enforces stricter parsing and error handling, prevents certain actions that were previously allowed but are considered bad practice, and makes it easier to write "secure" JavaScript. It can be applied to an entire script or individual functions.

What is the concept of Immutability?

Immutability means that once a data structure (like an object or array) is created, it cannot be changed. Any operation that would modify the structure instead returns a new, modified copy of the structure. This is a core concept in functional programming and is often used in modern JavaScript frameworks (like React with Redux) for predictable state management.

How do you achieve Immutability in JavaScript?
  • Using `const` (prevents reassignment, but not modification of contents).
  • Using methods that return new arrays/objects instead of modifying the original (e.g., `map`, `filter`, `slice`, spread syntax `...`).
  • Using libraries specifically designed for immutability (e.g., Immer, Immutable.js).
What is a Higher-Order Function?

A higher-order function is a function that either:

  • Takes one or more functions as arguments.
  • Returns a function.

Examples include `map`, `filter`, `reduce`, `setTimeout`, `addEventListener`.

What is a Pure Function?

A pure function is a function that:

  • Always returns the same output for the same input (Determinism).
  • Has no side effects (Does not modify external state or have observable interactions with the outside world other than returning a value).

Pure functions are easier to test, reason about, and can be memoized (cache their results).

What is Memoization?

Memoization is an optimization technique used to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.

        
function memoizedAddTo256() {
  const cache = {};
  return function(num) {
    if (num in cache) {
      console.log("Fetching from cache...");
      return cache[num];
    } else {
      console.log("Calculating...");
      cache[num] = num + 256;
      return cache[num];
    }
  };
}

const memoized = memoizedAddTo256();
console.log(memoized(10)); // Calculating... 266
console.log(memoized(10)); // Fetching from cache... 266
    
    
What is Recursion?

Recursion is a programming technique where a function calls itself to solve a problem. A recursive function must have a base case (a condition to stop the recursion) to prevent infinite loops.

        
function factorial(n) {
  if (n === 0) { // Base case
    return 1;
  }
  return n * factorial(n - 1); // Recursive call
}

console.log(factorial(5)); // 120
    
    
What is the difference between `let` and `var` in loops?

This highlights the difference in scoping:

  • With `var`, the loop variable is function-scoped. If you use `var` in a loop with closures (e.g., inside a `setTimeout`), the closure will capture the *final* value of the variable after the loop finishes.
  • With `let`, the loop variable is block-scoped. A new variable is created for each iteration of the loop, so closures inside the loop capture the correct value for that iteration.
        
// Using var (incorrect behavior with closure)
for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log('var i:', i); // Output: 3, 3, 3 (after loop finishes)
  }, 100);
}

// Using let (correct behavior with closure)
for (let j = 0; j < 3; j++) {
  setTimeout(function() {
    console.log('let j:', j); // Output: 0, 1, 2
  }, 100);
}
    
    
What is the difference between `Array.prototype.forEach()` and `Array.prototype.map()`?
  • `forEach()`: Iterates over array elements and executes a provided function for each element. It does *not* return a new array; its purpose is side effects (like logging or modifying external state).
  • `map()`: Creates a *new* array by applying a function to each element of the original array. It always returns a new array of the same length.
What is the difference between `Array.prototype.filter()` and `Array.prototype.find()`?
  • `filter()`: Returns a *new array* containing *all* elements that satisfy a provided testing function.
  • `find()`: Returns the *first* element in the array that satisfies a provided testing function. If no elements satisfy the test, it returns `undefined`.
What is the `Set` object?

A `Set` object (ES6) is a collection of unique values. You can add values to a Set, check if a value exists, and iterate over its elements. It's useful for removing duplicate values from an array.

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

console.log(mySet.has(2)); // true
mySet.add(5);
console.log(mySet.size); // 5
    
    
What is the `Map` object?

A `Map` object (ES6) is a collection of key-value pairs, similar to objects, but with a few key differences:

  • Keys can be of any data type (including objects and functions), not just strings or Symbols.
  • The order of elements is preserved.
  • It's easier to get the size of a Map (`map.size`).
        
const myMap = new Map();
myMap.set('name', 'Alice');
myMap.set(1, 'one');
myMap.set({}, 'empty object key');

console.log(myMap.get('name')); // "Alice"
console.log(myMap.has(1)); // true
console.log(myMap.size); // 3
    
    
What is the difference between `Map` and `Object`?
  • Keys: Map keys can be any type; Object keys are limited to strings and Symbols.
  • Order: Map preserves insertion order; Object key order is not guaranteed (though modern JS engines often preserve order for string keys).
  • Size: Map has a `.size` property; Object size needs to be calculated (e.g., `Object.keys(obj).length`).
  • Iteration: Maps are directly iterable; iterating over Objects requires methods like `Object.keys()`, `Object.values()`, or `Object.entries()`.
  • Performance: Maps can be more performant for frequent additions and deletions of key-value pairs.
What is the Temporal Dead Zone (TDZ)?

The Temporal Dead Zone is the period between the declaration of `let` or `const` variables and their initialization. Accessing these variables within the TDZ results in a `ReferenceError`. This is different from `var`, which would result in `undefined` due to hoisting.

Explain Promises chaining.

Promise chaining is a common pattern where you chain multiple `.then()` calls together to handle a sequence of asynchronous operations. Each `.then()` returns a *new* Promise, allowing you to continue chaining. The result of one `.then()` becomes the input for the next `.then()`. Errors can be caught by a single `.catch()` at the end of the chain.

        
fetch('url1')
  .then(response => response.json())
  .then(data => {
    console.log('First data:', data);
    return fetch('url2?id=' + data.id); // Return a new Promise
  })
  .then(response => response.json())
  .then(moreData => {
    console.log('Second data:', moreData);
  })
  .catch(error => {
    console.error('An error occurred:', error);
  });
    
    
What is the difference between `Promise.all` and `Promise.race`?
  • `Promise.all([promises])`: Takes an array of Promises and returns a new Promise that fulfills when *all* of the input Promises fulfill. The result is an array of the fulfillment values in the same order as the input Promises. If any of the input Promises reject, the returned Promise rejects with the reason of the first rejected Promise.
  • `Promise.race([promises])`: Takes an array of Promises and returns a new Promise that settles (fulfills or rejects) as soon as *any* of the input Promises settle. The result is the fulfillment value or rejection reason of the first Promise to settle.
What are Generators? How do they differ from regular functions?

Generators (ES6) are functions that can be paused and resumed. They are defined using `function*` and use the `yield` keyword to pause execution and return a value. When the generator is resumed, it continues execution from where it left off. They return an Iterator object.

Difference from regular functions: Regular functions run to completion; Generators can pause and yield multiple values over time.

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

const generator = myGenerator();
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 }
    
    
What is an Iterator?

An Iterator is an object that defines a sequence and potentially a return value upon its termination. It must implement a `next()` method, which returns an object with two properties: `value` (the next item in the sequence) and `done` (a boolean indicating if the sequence has finished). Many built-in JavaScript types are iterable (e.g., Arrays, Strings, Maps, Sets).

What is the difference between `let` and `const` with regards to mutability?

`let` and `const` control *reassignment* of the variable name, not the mutability of the value itself. A variable declared with `let` can be reassigned to a different value. A variable declared with `const` cannot be reassigned. The mutability of the *value* depends on its data type (primitives are immutable, objects/arrays are mutable).

What is the `Proxy` object?

The `Proxy` object (ES6) allows you to create an object that can be used in place of the original object, but which can intercept and redefine fundamental operations for that object (like property lookup, assignment, enumeration, function invocation, etc.). This is done using "traps" defined in a handler object.

        
const target = { message1: 'hello', message2: 'world' };
const handler = {
  get(target, prop) {
    if (prop === 'message2') {
      return 'goodbye';
    }
    return target[prop];
  }
};

const proxy = new Proxy(target, handler);

console.log(proxy.message1); // hello
console.log(proxy.message2); // goodbye
    
    
What is the `Reflect` object?

The `Reflect` object (ES6) provides a set of static methods that mirror corresponding methods on the Proxy handler object. It allows you to perform the default behavior of operations that can be intercepted by a Proxy. It's often used within Proxy traps to forward operations to the original object.

What are Symbols?

Symbols (ES6) are primitive values that are guaranteed to be unique. They are often used as object property keys to avoid naming conflicts, as a Symbol key will not clash with any other property key (including other Symbols) unless they are the exact same Symbol.

        
const mySymbol = Symbol('description');
const anotherSymbol = Symbol('description');

console.log(mySymbol === anotherSymbol); // false (Symbols are unique)

const obj = {};
obj[mySymbol] = 'value';
console.log(obj[mySymbol]); // "value"
console.log(Object.keys(obj)); // [] (Symbol keys are not enumerable by default)
    
    
What is the difference between Shallow Copy and Deep Copy?
  • Shallow Copy: Creates a new object or array, but the nested objects or arrays within it are still references to the original nested structures. Changes to nested structures in the copy will affect the original.
  • Deep Copy: Creates a completely new object or array and recursively copies all nested objects and arrays. Changes to the deep copy do not affect the original.

Methods for shallow copy: Spread syntax (`...`), `Object.assign()`. Methods for deep copy: `JSON.parse(JSON.stringify(obj))` (simple cases), structured cloning API, or libraries like Lodash's `_.cloneDeep()`.

How does the spread operator (`...`) perform when copying nested objects/arrays?

The spread operator performs a *shallow* copy. If the original object/array contains nested objects or arrays, the spread operator copies the *references* to those nested structures, not the nested structures themselves.

What is the Global Object in JavaScript?

The global object is an object that is always available in the global scope. In browsers, it's typically `window`. In Node.js, it's `global`. Variables declared with `var` in the global scope become properties of the global object.

What is the `eval()` function? Is it recommended?

`eval(string)` executes a string of JavaScript code. It is generally **not recommended** due to security risks (executing arbitrary code from potentially untrusted sources), performance issues (the browser cannot optimize code passed to `eval`), and debugging difficulties.

What is the difference between attributes and properties in HTML elements?
  • Attributes: Defined in the HTML markup (e.g., ``). They are the initial state of the element.
  • Properties: Represent the current state of the DOM element object. They are JavaScript properties of the element object. Properties can be read and modified using JavaScript. Some properties are directly mapped to attributes, while others are not. Changes to properties might not always reflect in the HTML markup.
        


const input = document.getElementById('myInput');
console.log(input.getAttribute('value')); // "initial value" (attribute)
console.log(input.value); // "initial value" (property)

input.value = "new value"; // Changing the property
console.log(input.getAttribute('value')); // Still "initial value" (attribute might not update)
console.log(input.value); // "new value" (property reflects current state)
    
    
What is the Virtual DOM? (Related to frameworks like React)

The Virtual DOM is a programming concept where a virtual representation of the UI is kept in memory and synced with the "real" DOM. When the state of the application changes, the Virtual DOM is updated, then compared to the previous Virtual DOM state (diffing). Only the necessary changes are then applied to the real DOM, which is a slower operation. This process minimizes direct manipulation of the real DOM, leading to better performance in many cases.

What is JSX? (Related to React)

JSX (JavaScript XML) is a syntax extension for JavaScript, commonly used with React. It looks like HTML but is actually a way to write JavaScript code that describes the structure of the UI. JSX expressions are transformed into regular JavaScript function calls (like `React.createElement()`) during the build process.

        
// JSX example
const element = 

Hello, {name}!

; // This gets compiled to something like: // const element = React.createElement("h1", null, "Hello, ", name, "!");
What is the difference between controlled and uncontrolled components in React? (Framework-specific)
  • Controlled Components: Form elements (like `<input>`, `<textarea>`, `<select>`) whose values are managed by the component's state. The state is the "single source of truth." Changes to the input update the state, which in turn updates the input's value.
  • Uncontrolled Components: Form elements whose values are managed by the DOM itself. You typically access their values using a ref.
What is state in React? (Framework-specific)

State in React is an object that holds data that might change over time and affects the rendering of a component. When the state of a component changes, React re-renders the component and its children. State should be managed carefully and updated using methods like `setState` (class components) or the state hook (`useState`) in functional components.

What are props in React? (Framework-specific)

Props (short for properties) are a way to pass data from a parent component to a child component in React. Props are read-only and should not be modified by the child component. They are used to configure child components.

What is the React component lifecycle? (For class components - Hooks are the modern alternative)

The component lifecycle refers to the different phases a component goes through from its creation to its removal from the DOM. Key lifecycle methods in class components include:

  • Mounting: `constructor`, `static getDerivedStateFromProps`, `render`, `componentDidMount`
  • Updating: `static getDerivedStateFromProps`, `shouldComponentUpdate`, `render`, `getSnapshotBeforeUpdate`, `componentDidUpdate`
  • Unmounting: `componentWillUnmount`
What are React Hooks? (Framework-specific)

React Hooks are functions that let you "hook into" React features from functional components. They allow you to use state and other React features (like the component lifecycle) without writing class components. Examples: `useState`, `useEffect`, `useContext`, `useReducer`, `useRef`.

Explain the `useEffect` hook. (Framework-specific)

The `useEffect` hook in React is used to perform side effects in functional components (e.g., fetching data, subscribing to events, manually manipulating the DOM). It runs after the component renders. You can control when the effect runs by providing a dependency array as the second argument. An empty dependency array `[]` means the effect runs only once after the initial render (like `componentDidMount`). Omitting the dependency array means the effect runs after every render.

What is Context API in React? (Framework-specific)

The Context API provides a way to share data (like user authentication status, themes, or settings) between components without having to pass props down manually through every level of the component tree (prop drilling). It consists of a Provider (to provide the value) and Consumers (to consume the value).

What is Redux? (State management library)

Redux is a predictable state container for JavaScript applications. It's often used with React, but can be used with any JavaScript library. Redux follows a strict unidirectional data flow and has three core principles:

  • Single source of truth (one store).
  • State is read-only (can only be changed by dispatching actions).
  • Changes are made with pure functions (Reducers).
What are Actions, Reducers, and Store in Redux? (State management library)
  • Actions: Plain JavaScript objects that describe what happened (e.g., `{ type: 'ADD_TODO', text: 'Buy milk' }`). They are the only way to trigger a state change.
  • Reducers: Pure functions that take the current state and an action as input and return a *new* state. They specify how the application's state changes in response to actions.
  • Store: Holds the application's state. It's created by combining the reducers. The store has methods like `dispatch` (to dispatch actions) and `getState` (to get the current state).
What is Node.js?

Node.js is a JavaScript runtime environment that allows you to run JavaScript code outside of a web browser. It's built on Chrome's V8 JavaScript engine. Node.js is commonly used for building server-side applications, command-line tools, and build tools.

What is npm?

npm (Node Package Manager) is the default package manager for Node.js. It's a vast registry of open-source JavaScript packages and a command-line tool for installing, managing, and publishing packages.

What is the difference between dependencies and devDependencies in `package.json`?
  • `dependencies`: Packages required for your application to run in production (e.g., a web framework, a utility library).
  • `devDependencies`: Packages required only during development and building (e.g., testing frameworks, linters, bundlers, transpilers).
What is a callback function?

A callback function is a function passed as an argument to another function, which is then executed inside the outer function at a later time (often after an asynchronous operation completes).

        
function fetchData(url, callback) {
  // Simulate fetching data asynchronously
  setTimeout(() => {
    const data = "Some data from " + url;
    callback(data); // Execute the callback with the data
  }, 1000);
}

fetchData("api/users", function(result) {
  console.log("Received data:", result);
});
    
    
What is Callback Hell?

Callback Hell (also known as the Pyramid of Doom) is a situation that arises when dealing with multiple nested callbacks, especially in asynchronous operations. It makes the code difficult to read, understand, and maintain due to the deeply nested structure.

        
getData(function(a) {
  getMoreData(a, function(b) {
    getEvenMoreData(b, function(c) {
      // ... deeply nested code
    });
  });
});
    
    

Promises and `async`/`await` are solutions to Callback Hell.

What is CORS?

CORS (Cross-Origin Resource Sharing) is a browser security mechanism that restricts web pages from making requests to a different domain than the one from which the page was served. It's a security measure to prevent malicious websites from making unauthorized requests to other sites on behalf of the user. The server needs to send appropriate CORS headers to allow cross-origin requests.

What is the difference between `innerHTML` and `textContent`?
  • `innerHTML`: Gets or sets the HTML content of an element. When setting, it parses the string as HTML.
  • `textContent`: Gets or sets the text content of an element. When setting, it treats the string as plain text, preventing HTML injection. It's generally safer for setting text content.
        
const div = document.getElementById('myDiv');
div.innerHTML = 'Bold Text'; // Renders bold text
div.textContent = 'Bold Text'; // Displays "Bold Text" as plain text
    
    
What is the difference between `document.write()` and manipulating the DOM?

`document.write()` writes HTML directly to the document stream. If called after the page has loaded, it will overwrite the entire document content, effectively clearing the page. Manipulating the DOM (using methods like `appendChild`, `createElement`, `textContent`, etc.) is the standard and recommended way to dynamically update the content of a web page without replacing the entire document.

What is the difference between `let` and `var` regarding global object properties?

Variables declared with `var` in the global scope become properties of the global object (`window` in browsers). Variables declared with `let` and `const` in the global scope do not become properties of the global object.

            
var globalVar = 1;
let globalLet = 2;

console.log(window.globalVar); // 1 (in browser)
console.log(window.globalLet); // undefined (in browser)
    
    
What is the difference between `undefined` and "not defined"?
  • `undefined`: A value assigned to a variable that has been declared but not initialized. It's a valid data type.
  • "not defined": A `ReferenceError` that occurs when you try to access a variable that has not been declared in the current scope.
            
let myVar;
console.log(myVar); // undefined

// console.log(anotherVar); // ReferenceError: anotherVar is not defined
    
    
What is method chaining?

Method chaining is a programming pattern where multiple methods are called sequentially on the same object, with each method returning the object itself (or a related object) to allow the next method in the chain to be called. This creates a more concise and readable code style.

            
// Example with jQuery
// $('selector').addClass('my-class').css('color', 'red').hide();

// Example with Array methods
const result = [1, 2, 3]
  .map(num => num * 2) // Returns a new array [2, 4, 6]
  .filter(num => num > 3); // Returns a new array [4, 6]
console.log(result); // [4, 6]
    
    
What is the purpose of `Object.freeze()`?

`Object.freeze()` freezes an object, preventing new properties from being added to it, existing properties from being removed, and existing properties or their enumerability, configurability, or writability from being changed. It performs a shallow freeze (nested objects are not frozen).

What is the purpose of `Object.seal()`?

`Object.seal()` seals an object, preventing new properties from being added to it and marking all existing properties as non-configurable. Existing properties can still be changed as long as they are writable.

What is the difference between `Object.freeze()` and `Object.seal()`?
  • `freeze()`: Prevents adding, removing, or changing *any* properties.
  • `seal()`: Prevents adding or removing properties, but allows changing *existing* writable properties.
What is the purpose of the `instanceof` operator?

The `instanceof` operator tests whether an object has the `prototype` property of a constructor in its prototype chain. It checks if an object is an instance of a specific class or constructor function.

            
class Dog {}
const myDog = new Dog();
console.log(myDog instanceof Dog); // true
console.log(myDog instanceof Object); // true
    
    
What is the purpose of the `typeof` operator?

The `typeof` operator returns a string indicating the type of the operand. It's primarily used for checking primitive data types.

            
console.log(typeof "hello"); // "string"
console.log(typeof 123);    // "number"
console.log(typeof true);   // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null);   // "object" (historical bug, still returns "object")
console.log(typeof {});     // "object"
console.log(typeof []);     // "object"
console.log(typeof function() {}); // "function"
console.log(typeof Symbol()); // "symbol"
console.log(typeof 1n);     // "bigint"
    
    
Why does `typeof null` return "object"?

This is a historical bug in JavaScript that has persisted for compatibility reasons. When the `typeof` operator was first implemented, values were represented by a type tag and a value. The type tag for objects was 000, and `null` was represented as the NULL pointer (0). Thus, `null` had the same type tag as objects.

What is the difference between `document.readyState` values?

`document.readyState` is a property that describes the loading state of the document.

  • `loading`: The document is still loading.
  • `interactive`: The document has been parsed, but sub-resources (like images, stylesheets) may still be loading. DOM is ready.
  • `complete`: The document and all sub-resources have finished loading.
What is the use of `requestAnimationFrame`?

`requestAnimationFrame(callback)` is a browser API used for performing animations. It tells the browser that you want to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. This results in smoother animations as the browser can optimize the rendering loop.

What is the difference between `==` and `Object.is()`?
  • `==`: Equality operator with type coercion.
  • `Object.is(value1, value2)` (ES6): Performs strict equality comparison (`===`) but with two special cases:
    • `Object.is(NaN, NaN)` is `true` (whereas `NaN === NaN` is `false`).
    • `Object.is(0, -0)` is `false` (whereas `0 === -0` is `true`).

`Object.is()` is generally considered more accurate for checking if two values are truly the same.

What is the purpose of the `eval()` function? Is it recommended? (Revisited)

Executes a string as JavaScript code. Not recommended due to security, performance, and debugging issues.

What are WeakMaps and WeakSets?
  • `WeakMap`: A collection of key/value pairs where keys are objects and are weakly referenced. If an object used as a key is no longer referenced elsewhere, it can be garbage collected. Useful for associating data with objects without preventing garbage collection.
  • `WeakSet`: A collection of unique objects where objects are weakly referenced. If an object in a WeakSet is no longer referenced elsewhere, it can be garbage collected. Useful for tracking object instances.
What is the difference between `for...in` and `Object.keys()`?
  • `for...in`: Iterates over enumerable property *names* (keys) of an object, including inherited enumerable properties.
  • `Object.keys(obj)`: Returns an array of an object's own (non-inherited) enumerable property *names* (keys). Does not include Symbol keys.
What is the difference between `Object.keys()`, `Object.values()`, and `Object.entries()`?
  • `Object.keys(obj)`: Returns an array of the object's own enumerable property *names* (keys).
  • `Object.values(obj)` (ES8): Returns an array of the object's own enumerable property *values*.
  • `Object.entries(obj)` (ES8): Returns an array of the object's own enumerable `[key, value]` pairs.
What is the purpose of the `yield*` expression in Generators?

The `yield*` expression is used within a generator function to delegate to another iterable object (another generator, an array, etc.). It effectively iterates over the delegated iterable and yields each value from it.

            
function* generator1() {
  yield 1;
  yield 2;
}

function* generator2() {
  yield 3;
  yield* generator1(); // Delegates to generator1
  yield 4;
}

const gen = generator2();
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 4, done: false }
console.log(gen.next()); // { value: undefined, done: true }
    
    
What is the difference between `console.log()` and `return`?
  • `console.log()`: A function used for printing output to the browser console or Node.js terminal. It's for debugging and displaying information, but it doesn't affect the flow or result of a function.
  • `return`: A keyword used inside a function to specify the value that the function should output. When a `return` statement is executed, the function stops executing, and the specified value is returned to the caller.
            
function exampleFunction() {
  console.log("This will be printed.");
  return "This is the return value.";
  console.log("This will NOT be printed."); // Code after return is unreachable
}

const result = exampleFunction();
console.log(result); // Output: "This is the return value."