JS
…

Interview Q&A

Top 311 JavaScript interview questions

Coding classics (palindrome, anagram, reverse string, reverse numbers) plus callbacks, promises, closures, the event loop, and the trick questions interviewers still ask. Search or scroll — practice links sit on the algorithm questions.

हिंदी Q&A⏱ Timed mock interview

Coding problems

Q1 of 311 · Coding problems

Reverse a string

Write a function that reverses a string. What are the common approaches and their trade-offs?

The classic interview answer is to split into characters, reverse the array, and join. You can also build a new string from the end with a loop, or use two pointers on an array of characters. Strings are immutable in JavaScript, so every concatenation in a loop copies — split/reverse/join is simple and fast enough for interviews. Mention Unicode: spreading [...str] handles most BMP characters better than split(""), and grapheme clusters (emoji with modifiers) need Intl.Segmenter.

Examples

JavaScript
function reverseString(text) {
  return text.split("").reverse().join("");
}

function reverseSpread(text) {
  return [...text].reverse().join("");
}

reverseString("hello"); // "olleh"

Practice reverse string →

Q2 of 311 · Coding problems

Reverse a number

How do you reverse an integer such as 1234 → 4321? What about negatives and trailing zeros?

Turn the number into a string, reverse the digits, then convert back with Number or parseInt. Keep the sign aside if the value can be negative. Trailing zeros in the original number become leading zeros after reverse and disappear as a number (1200 → 21). Interviewers often also want an arithmetic version: repeatedly take n % 10 and build reversed = reversed * 10 + digit. Watch overflow if they mention 32-bit ints — JavaScript Number is a float, so discuss BigInt or a 32-bit clamp if they ask.

Examples

JavaScript
function reverseNumber(n) {
  const sign = Math.sign(n);
  const reversed = Number(String(Math.abs(n)).split("").reverse().join(""));
  return sign * reversed;
}

function reverseNumberMath(n) {
  const sign = n < 0 ? -1 : 1;
  let x = Math.abs(n);
  let out = 0;
  while (x > 0) {
    out = out * 10 + (x % 10);
    x = Math.floor(x / 10);
  }
  return sign * out;
}

reverseNumber(1234); // 4321
reverseNumber(-90);  // -9

Q3 of 311 · Coding problems

Palindrome (string)

How do you check whether a string is a palindrome?

A palindrome reads the same forwards and backwards. Normalize first: lowercase, and often strip non-letters if the prompt says so. Then compare the string to its reverse, or walk two pointers from both ends until they meet. Two pointers uses O(1) extra memory besides the cleaned string. Call out case: "Level" should pass if you ignore case.

Examples

JavaScript
function isPalindrome(text) {
  const clean = text.toLowerCase().replace(/[^a-z0-9]/g, "");
  return clean === [...clean].reverse().join("");
}

function isPalindromePointers(text) {
  const s = text.toLowerCase();
  let i = 0;
  let j = s.length - 1;
  while (i < j) {
    if (s[i] !== s[j]) return false;
    i++;
    j--;
  }
  return true;
}

isPalindrome("Level"); // true
isPalindrome("js");    // false

Practice palindrome →

Q4 of 311 · Coding problems

Palindrome (number)

How do you check if an integer is a palindrome without converting it to a string (optional follow-up)?

The string path is reverseNumber(n) === n (and reject negatives if the problem says so — -121 reversed as a number is not 121). The math path reverses half the digits: build reversed from n % 10 until reversed >= remaining n, then check equality or equality after dropping the middle digit for odd length. Negatives are not palindromes in the usual LeetCode rule.

Examples

JavaScript
function isPalindromeNumber(n) {
  if (n < 0) return false;
  return n === Number(String(n).split("").reverse().join(""));
}

isPalindromeNumber(121);  // true
isPalindromeNumber(-121); // false

Q5 of 311 · Coding problems

Anagram

How do you check if two strings are anagrams?

Anagrams use the same characters with the same frequencies, order ignored. Normalize case (and spaces if the prompt requires). Two solid answers: sort both strings and compare, or count characters in a Map / array of 26 letters. Sorting is O(n log n) and short to write. Counting is O(n) and shows you think about frequency maps — mention that in interviews.

Examples

JavaScript
function isAnagram(a, b) {
  const norm = (s) => s.toLowerCase().split("").sort().join("");
  return norm(a) === norm(b);
}

function isAnagramCount(a, b) {
  if (a.length !== b.length) return false;
  const counts = new Map();
  for (const ch of a.toLowerCase()) counts.set(ch, (counts.get(ch) ?? 0) + 1);
  for (const ch of b.toLowerCase()) {
    const next = (counts.get(ch) ?? 0) - 1;
    if (next < 0) return false;
    counts.set(ch, next);
  }
  return true;
}

isAnagram("listen", "silent"); // true

Practice anagram →

Q6 of 311 · Coding problems

FizzBuzz

Implement FizzBuzz for 1..n.

For each integer, if it is divisible by 15 print FizzBuzz, else if by 3 print Fizz, else if by 5 print Buzz, else the number. Check 15 first (or 3 and 5 together) so you do not print only Fizz. Interviewers watch whether you use % and write a clear loop. A function that returns the label for one n is easier to test than printing.

Examples

JavaScript
function fizzBuzz(n) {
  if (n % 15 === 0) return "FizzBuzz";
  if (n % 3 === 0) return "Fizz";
  if (n % 5 === 0) return "Buzz";
  return n;
}

for (let i = 1; i <= 15; i++) console.log(fizzBuzz(i));

Practice FizzBuzz →

Q7 of 311 · Coding problems

Factorial

Write factorial(n). Iterative vs recursive?

n! is 1 * 2 * … * n, and 0! is 1. A loop is safer (no stack growth). Recursion is factorial(n) = n * factorial(n - 1) with base n <= 1. Large n overflows Number — mention BigInt for n > 20 or so. Interviewers like seeing the base case first.

Examples

JavaScript
function factorial(n) {
  let result = 1;
  for (let i = 2; i <= n; i++) result *= i;
  return result;
}

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

factorial(5); // 120

Practice this →

Q8 of 311 · Coding problems

Fibonacci

Return the nth Fibonacci number. Why is naive recursion a trap?

F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2). Naive recursion recomputes the same subproblems exponentially. Prefer a loop that stores two previous values, or memoization. Mention time O(n) iterative vs O(2^n) naive. Some prompts want an array of the sequence instead of one number.

Examples

JavaScript
function fib(n) {
  if (n <= 1) return n;
  let a = 0;
  let b = 1;
  for (let i = 2; i <= n; i++) {
    const next = a + b;
    a = b;
    b = next;
  }
  return b;
}

fib(7); // 13

Q9 of 311 · Coding problems

Count vowels

Count a, e, i, o, u in a string, case-insensitive.

Lowercase the string, then filter characters that appear in "aeiou", or increment a counter in a loop. Decide whether y counts — usually no unless they say so. For Unicode, stick to English vowels unless asked.

Examples

JavaScript
function countVowels(text) {
  return [...text.toLowerCase()].filter((ch) => "aeiou".includes(ch)).length;
}

countVowels("JavaScript"); // 3

Practice this →

Q10 of 311 · Coding problems

Find the maximum in an array

How do you find the largest number in an array?

Math.max(...arr) is the one-liner, but a huge array can exceed the spread argument limit. A loop (or reduce) is the production answer. Handle empty arrays: throw, return undefined, or -Infinity — say which you chose.

Examples

JavaScript
function max(arr) {
  if (arr.length === 0) return undefined;
  let best = arr[0];
  for (const n of arr) if (n > best) best = n;
  return best;
}

max([3, 9, 2]); // 9

Q11 of 311 · Coding problems

Remove duplicates

Remove duplicates from an array and keep first-seen order.

[...new Set(arr)] is the expected modern answer. A loop with a Set of seen values works if you cannot use Set, or if you need a custom equality. Objects are compared by reference in Set, not by deep value.

Examples

JavaScript
function unique(arr) {
  return [...new Set(arr)];
}

unique([1, 2, 2, 3, 1]); // [1, 2, 3]

Practice this →

Q12 of 311 · Coding problems

Flatten a nested array

Flatten nested arrays to a single level or fully deep.

arr.flat() is one level; arr.flat(Infinity) is full flatten. Recursion or a stack shows you can do it by hand: if the item is an array, spread its flatten, else push. Mention concat vs push and that flat does not flatten array-likes unless you convert them.

Examples

JavaScript
function flatten(arr) {
  return arr.flat(Infinity);
}

function flattenRec(arr) {
  return arr.reduce(
    (out, item) => out.concat(Array.isArray(item) ? flattenRec(item) : item),
    [],
  );
}

flatten([1, [2, [3, 4]], 5]); // [1, 2, 3, 4, 5]

Practice this →

Q13 of 311 · Coding problems

Two sum

Find two indices whose values add up to a target.

Brute force is two nested loops O(n²). The interview solution is a Map from value → index: for each number, look up target - number. If present, return those indices; else store the current number. That is O(n) time and O(n) space. Ask if the array is sorted — then two pointers work without a map.

Examples

JavaScript
function twoSum(nums, target) {
  const seen = new Map();
  for (let i = 0; i < nums.length; i++) {
    const need = target - nums[i];
    if (seen.has(need)) return [seen.get(need), i];
    seen.set(nums[i], i);
  }
}

twoSum([2, 7, 11, 15], 9); // [0, 1]

Practice this →

Q14 of 311 · Coding problems

First non-repeating character

Return the first character that appears exactly once.

Count frequencies in a Map (or object), then scan the string once more and return the first char whose count is 1. One pass with a queue is possible but the two-pass Map is clearer in interviews.

Examples

JavaScript
function firstUnique(text) {
  const counts = new Map();
  for (const ch of text) counts.set(ch, (counts.get(ch) ?? 0) + 1);
  for (const ch of text) if (counts.get(ch) === 1) return ch;
}

firstUnique("aabbcde"); // "c"

Q15 of 311 · Coding problems

Title case / capitalize words

Capitalize the first letter of every word.

Split on spaces, map each word to first char upper + rest lower, join. Watch extra spaces and empty words. Intl and locale can matter for i/İ — mention if they care about i18n.

Examples

JavaScript
function titleCase(text) {
  return text
    .split(" ")
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .join(" ");
}

titleCase("learn javascript now"); // "Learn Javascript Now"

Practice this →

Q16 of 311 · Coding problems

Character frequency

Build a frequency map of characters in a string.

Loop the string and increment Map or object counts. Objects coerce keys to strings; Map keeps insertion order and any key type. For interviews, Map is a clean default.

Example

JavaScript
function frequencies(text) {
  const map = new Map();
  for (const ch of text) map.set(ch, (map.get(ch) ?? 0) + 1);
  return map;
}

Q17 of 311 · Coding problems

Reverse words in a sentence

Reverse the order of words, or reverse each word in place.

Clarify the prompt. Reverse word order: split on spaces, reverse the array, join. Reverse each word: split, reverse each word’s characters, join. Multiple spaces often should collapse — split(/\s+/) and trim.

Examples

JavaScript
function reverseWordOrder(text) {
  return text.trim().split(/\s+/).reverse().join(" ");
}

function reverseEachWord(text) {
  return text
    .split(" ")
    .map((word) => [...word].reverse().join(""))
    .join(" ");
}

reverseWordOrder("I love JS"); // "JS love I"

Q18 of 311 · Coding problems

Check prime

How do you test whether n is prime?

Numbers < 2 are not prime. Check divisibility from 2 to Math.sqrt(n). Even-number skip after 2 is a small optimization. Do not loop to n-1 — that is slow and a common miss.

Example

JavaScript
function isPrime(n) {
  if (n < 2) return false;
  if (n === 2) return true;
  if (n % 2 === 0) return false;
  for (let d = 3; d * d <= n; d += 2) {
    if (n % d === 0) return false;
  }
  return true;
}

Q19 of 311 · Coding problems

Sum of digits

Sum the digits of a number until a single digit (optional digital root).

Convert to string and reduce, or use n % 10 in a loop. Digital root can use n % 9 with a 9→9 special case. Start with the loop so they see you understand remainders.

Examples

JavaScript
function sumDigits(n) {
  let sum = 0;
  let x = Math.abs(n);
  while (x > 0) {
    sum += x % 10;
    x = Math.floor(x / 10);
  }
  return sum;
}

sumDigits(405); // 9

Q20 of 311 · Coding problems

Missing number in 0..n

An array contains n distinct numbers from 0 to n except one missing. Find it.

Sum formula n*(n+1)/2 minus the array sum, or XOR all indices and values. XOR avoids overflow talk in other languages. Sorting then scanning is the slower fallback.

Example

JavaScript
function missingNumber(nums) {
  const n = nums.length;
  const expected = (n * (n + 1)) / 2;
  const actual = nums.reduce((a, b) => a + b, 0);
  return expected - actual;
}

Q21 of 311 · Coding problems

Chunk an array

Split an array into groups of size k.

Loop with i += size and push arr.slice(i, i + size). Last chunk may be shorter. Avoid mutating the original if they did not ask for that.

Examples

JavaScript
function chunk(arr, size) {
  const out = [];
  for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
  return out;
}

chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]

Practice this →

Q22 of 311 · Coding problems

Rotate an array

Rotate right by k steps.

k %= length so large k is cheap. Then concat slice(-k) with slice(0, -k), or reverse the whole array then reverse the two parts (in-place interview classic).

Examples

JavaScript
function rotateRight(arr, k) {
  const n = arr.length;
  if (n === 0) return arr;
  k %= n;
  return arr.slice(-k).concat(arr.slice(0, -k));
}

rotateRight([1, 2, 3, 4, 5], 2); // [4, 5, 1, 2, 3]

Q23 of 311 · Coding problems

Second largest number

Find the second largest unique value in an array.

One pass: track largest and second. Skip equals to largest if they want unique. Sorting and picking index 1 is simpler but O(n log n). Empty or single-element arrays need a defined result (undefined).

Example

JavaScript
function secondLargest(arr) {
  let first = -Infinity;
  let second = -Infinity;
  for (const n of arr) {
    if (n > first) {
      second = first;
      first = n;
    } else if (n < first && n > second) {
      second = n;
    }
  }
  return second === -Infinity ? undefined : second;
}

Q24 of 311 · Coding problems

Balanced parentheses

Check whether brackets in a string are balanced.

Use a stack. Push opening brackets. On a closer, pop and ensure it matches. At the end the stack must be empty. Map closers to openers. This is the standard stack interview problem.

Examples

JavaScript
function isBalanced(text) {
  const pairs = { ")": "(", "]": "[", "}": "{" };
  const stack = [];
  for (const ch of text) {
    if ("([{".includes(ch)) stack.push(ch);
    else if (pairs[ch]) {
      if (stack.pop() !== pairs[ch]) return false;
    }
  }
  return stack.length === 0;
}

isBalanced("{[()]}"); // true

Q25 of 311 · Coding problems

Deep clone

How do you deep-clone an object in JavaScript?

structuredClone(value) is the modern built-in for most data (including dates, maps, cycling with some limits). JSON.parse(JSON.stringify(obj)) drops functions, undefined, and Dates become strings. A recursive copy handles plain objects/arrays but must track seen objects to avoid cycles. Mention lodash.cloneDeep only if they use it.

Examples

JavaScript
const copy = structuredClone({ user: { name: "Ada" }, tags: [1, 2] });

function deepClone(value, seen = new WeakMap()) {
  if (value === null || typeof value !== "object") return value;
  if (seen.has(value)) return seen.get(value);
  const out = Array.isArray(value) ? [] : {};
  seen.set(value, out);
  for (const key of Object.keys(value)) out[key] = deepClone(value[key], seen);
  return out;
}

Q26 of 311 · Coding problems

Debounce

Implement debounce(fn, ms).

Debounce waits until calls stop for ms, then runs once. Clear the previous timer on each call and start a new one. Used for search inputs. Contrast with throttle, which runs at most once per window. Mention leading vs trailing if they push.

Examples

JavaScript
function debounce(fn, ms) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), ms);
  };
}

const onType = debounce((q) => console.log("search", q), 300);

Q27 of 311 · Coding problems

Throttle

Implement throttle(fn, ms).

Throttle ensures fn runs at most once every ms. A simple version records lastRan and ignores calls that arrive too soon; a trailing-edge version schedules a timeout for the leftover wait. Used for scroll and resize handlers.

Example

JavaScript
function throttle(fn, ms) {
  let last = 0;
  return function (...args) {
    const now = Date.now();
    if (now - last >= ms) {
      last = now;
      fn.apply(this, args);
    }
  };
}

Q28 of 311 · Coding problems

Currying

What is currying? Implement a simple curry.

Currying turns f(a, b, c) into f(a)(b)(c). You return a new function until enough arguments are collected, then call the original. Contrast with partial application (fixing some args but not necessarily one at a time). Useful with map/compose.

Examples

JavaScript
function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) return fn.apply(this, args);
    return (...rest) => curried(...args, ...rest);
  };
}

const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);
curriedAdd(1)(2)(3); // 6

Q29 of 311 · Coding problems

Implement Function.prototype.bind

Write a simplified bind that fixes this and prepends arguments.

bind returns a new function. When that function runs, call the original with a bound this and concatenated args. Arrow functions cannot be bound — mention that. A full spec bind also works as a constructor; interviews usually accept apply-based bind.

Examples

JavaScript
Function.prototype.myBind = function (thisArg, ...boundArgs) {
  const fn = this;
  return function (...args) {
    return fn.apply(thisArg, [...boundArgs, ...args]);
  };
};

function greet(hi) {
  return hi + " " + this.name;
}
greet.myBind({ name: "Ada" }, "Hi")(); // "Hi Ada"

Q30 of 311 · Coding problems

Implement Array.prototype.map

Write map without using the built-in map.

Create a new array, loop indices, skip holes if you want spec-ish behavior, call callback(item, i, arr), push results. Do not mutate the original. Using thisArg is a plus.

Examples

JavaScript
function map(arr, fn) {
  const out = [];
  for (let i = 0; i < arr.length; i++) {
    if (i in arr) out.push(fn(arr[i], i, arr));
  }
  return out;
}

map([1, 2, 3], (n) => n * 2); // [2, 4, 6]

Q31 of 311 · Coding problems

Implement Array.prototype.filter

Write filter by hand.

New array, loop, push items for which the predicate is truthy. Same hole-skipping note as map. Return a shallow copy of kept elements, never the original reference.

Example

JavaScript
function filter(arr, fn) {
  const out = [];
  for (let i = 0; i < arr.length; i++) {
    if (i in arr && fn(arr[i], i, arr)) out.push(arr[i]);
  }
  return out;
}

Q32 of 311 · Coding problems

Implement Array.prototype.reduce

Write reduce, including the missing-initial-value case.

If initial value is provided, start from index 0 with that accumulator. If not, start accumulator as arr[0] and loop from 1 — throw on empty array. This is a common follow-up after map/filter.

Example

JavaScript
function reduce(arr, fn, initial) {
  let i = 0;
  let acc = initial;
  if (arguments.length < 3) {
    if (arr.length === 0) throw new TypeError("Reduce of empty array");
    acc = arr[0];
    i = 1;
  }
  for (; i < arr.length; i++) acc = fn(acc, arr[i], i, arr);
  return acc;
}

Q33 of 311 · Coding problems

Implement Promise.all

Write a Promise.all that resolves with results in order or rejects on the first failure.

Return a new Promise. If the list is empty, resolve []. Otherwise count remaining items. For each input, Promise.resolve(item) so non-promises work. Store results[index] so order matches input, not finish order. Reject on first rejection.

Example

JavaScript
function promiseAll(items) {
  return new Promise((resolve, reject) => {
    const list = [...items];
    if (list.length === 0) return resolve([]);
    const results = [];
    let left = list.length;
    list.forEach((item, i) => {
      Promise.resolve(item).then((value) => {
        results[i] = value;
        left -= 1;
        if (left === 0) resolve(results);
      }, reject);
    });
  });
}

Q35 of 311 · Coding problems

Bubble sort

Implement bubble sort and know its complexity.

Repeatedly swap adjacent items if they are out of order. After pass k, the last k items are sorted. O(n²) time, O(1) extra space. Say you would use the built-in sort in real code; they want the swap logic.

Example

JavaScript
function bubbleSort(arr) {
  const a = [...arr];
  for (let i = 0; i < a.length; i++) {
    for (let j = 0; j < a.length - 1 - i; j++) {
      if (a[j] > a[j + 1]) [a[j], a[j + 1]] = [a[j + 1], a[j]];
    }
  }
  return a;
}

Q36 of 311 · Coding problems

Swap two variables

Swap two values without a temporary variable.

Destructuring [a, b] = [b, a] is the JS way. XOR swap works for integers but is a trick and fails for objects. Addition/subtraction overflows in other languages. Prefer destructuring in interviews unless they ban it.

Example

JavaScript
let a = 3;
let b = 7;
[a, b] = [b, a];
// a === 7, b === 3

Q37 of 311 · Coding problems

GCD and LCM

Compute greatest common divisor and least common multiple.

Euclid’s algorithm: gcd(a, b) = gcd(b, a % b) until b is 0. LCM is abs(a * b) / gcd(a, b) (watch divide-by-zero). This shows you know remainders, not just loops.

Examples

JavaScript
function gcd(a, b) {
  a = Math.abs(a);
  b = Math.abs(b);
  while (b) [a, b] = [b, a % b];
  return a;
}

function lcm(a, b) {
  return Math.abs(a * b) / gcd(a, b);
}

Q38 of 311 · Coding problems

Armstrong number

Check whether a number equals the sum of its digits each raised to the count of digits.

153 is 1³+5³+3³. Count digits, then sum digit ** power. Compare to the original. Easy loop practice with % and Math.floor.

Example

JavaScript
function isArmstrong(n) {
  const digits = String(n).split("").map(Number);
  const p = digits.length;
  const sum = digits.reduce((acc, d) => acc + d ** p, 0);
  return sum === n;
}

Q39 of 311 · Coding problems

Intersection of two arrays

Return values that appear in both arrays.

Put one array in a Set, filter the other. If you need unique results, wrap in a Set again. Nested loops are the O(n*m) answer they do not want as the final solution.

Example

JavaScript
function intersection(a, b) {
  const setB = new Set(b);
  return [...new Set(a.filter((item) => setB.has(item)))];
}

Q40 of 311 · Coding problems

Merge two sorted arrays

Merge two sorted arrays into one sorted array.

Two pointers: pick the smaller head each time, then append leftovers. Concat + sort is easier but O(n log n) and ignores the sorted property. This is the merge step of merge sort.

Example

JavaScript
function mergeSorted(a, b) {
  const out = [];
  let i = 0;
  let j = 0;
  while (i < a.length && j < b.length) {
    if (a[i] <= b[j]) out.push(a[i++]);
    else out.push(b[j++]);
  }
  return out.concat(a.slice(i), b.slice(j));
}

Q41 of 311 · Coding problems

Longest word in a sentence

Return the first longest space-separated word.

Split on spaces, reduce comparing length. Tie-breaking: keep the first. Trim so leading spaces do not create empty words.

Examples

JavaScript
function longestWord(text) {
  return text.split(" ").reduce((best, word) => (word.length > best.length ? word : best), "");
}

longestWord("a lovely javascript"); // "javascript"

Practice this →

Q42 of 311 · Coding problems

Count occurrences of a value

How many times does a value appear in an array?

filter(x => x === value).length or a reduce. For objects, === is reference equality. For NaN, use Object.is or Number.isNaN because NaN !== NaN.

Example

JavaScript
function count(arr, value) {
  return arr.reduce((n, item) => n + (Object.is(item, value) ? 1 : 0), 0);
}

Q43 of 311 · Coding problems

Shuffle an array (Fisher–Yates)

How do you shuffle fairly?

Fisher–Yates: from the end, swap i with a random index ≤ i. Math.random() sort is biased — mention that if they propose it. Mutate a copy if you must not touch the original.

Example

JavaScript
function shuffle(arr) {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

Q44 of 311 · Coding problems

Memoize a function

Cache results of a pure function by arguments.

Store results in a Map keyed by JSON.stringify(args) (good enough for primitives). On call, return cache hit or compute and store. Does not work well with object keys unless you canonicalize them. Used in DP interviews as well as JS runtime questions.

Example

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

Q45 of 311 · Coding problems

Sleep with a Promise

Write a delay(ms) that you can await.

return new Promise(resolve => setTimeout(resolve, ms)). This is the standard way to pause in async functions without blocking the thread. Never busy-wait in a while loop.

Examples

JavaScript
function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function demo() {
  await delay(200);
  console.log("later");
}

Q46 of 311 · Coding problems

Retry a failing async function

Call fn up to n times until it succeeds.

Loop: try await fn(), return on success, catch and retry. After the last attempt, throw. Optional delay between tries. Shows you can combine async/await with control flow.

Example

JavaScript
async function retry(fn, attempts = 3) {
  let lastError;
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (err) {
      lastError = err;
    }
  }
  throw lastError;
}

Q47 of 311 · Coding problems

Group by a key

Group an array of objects by a property.

Object.groupBy exists in newer JS. By hand: reduce into an object of arrays. Missing keys become "undefined" unless you skip them. This is a very common data-shaping interview.

Example

JavaScript
function groupBy(arr, key) {
  return arr.reduce((acc, item) => {
    const k = item[key];
    (acc[k] ??= []).push(item);
    return acc;
  }, {});
}

Q48 of 311 · Coding problems

Deep equality

How would you compare two values deeply?

Object.is for primitives (handles NaN). For arrays, same length and recursive compare. For objects, same keys (order ignored) and recursive values. Dates compare getTime(). Avoid JSON.stringify — key order and undefined make it unreliable. Mention libraries for production.

Example

JavaScript
function deepEqual(a, b) {
  if (Object.is(a, b)) return true;
  if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
  const keysA = Object.keys(a);
  const keysB = Object.keys(b);
  if (keysA.length !== keysB.length) return false;
  return keysA.every((key) => deepEqual(a[key], b[key]));
}

Q49 of 311 · Coding problems

Range of numbers

Build an inclusive array from start to end.

Loop from start to end pushing integers. Array.from({ length }, (_, i) => start + i) is a tidy alternative. Confirm start <= end or handle reverse ranges.

Example

JavaScript
function range(start, end) {
  const out = [];
  for (let n = start; n <= end; n++) out.push(n);
  return out;
}

Practice this →

Language fundamentals

Q50 of 311 · Language fundamentals

JavaScript data types

What are the JavaScript data types?

Seven primitives: string, number, bigint, boolean, undefined, symbol, null. Everything else is an object (including arrays, functions, dates, maps). typeof null is "object" — a historic bug. typeof function is "function", a subtype of object. Ask for examples of boxing: "hi".length works because of a temporary String object.

Examples

JavaScript
typeof "Ada";          // "string"
typeof 42;             // "number"
typeof 10n;            // "bigint"
typeof true;           // "boolean"
typeof undefined;      // "undefined"
typeof Symbol("id");   // "symbol"
typeof null;           // "object"  ← historic bug
typeof [];             // "object"
typeof function () {}; // "function"

"hi".length; // 2 — engine briefly boxes the primitive as a String object

Q51 of 311 · Language fundamentals

Primitives vs objects

How do primitives differ from objects?

Primitives are immutable and compared by value. Objects are mutable and compared by reference. Assigning an object copies the reference, so two variables can point at the same memory. Passing an object into a function lets the function mutate its properties, but reassigning the parameter does not change the caller’s binding.

Examples

JavaScript
let a = 10;
let b = a;
b = 20;
console.log(a, b); // 10 20  — copied by value

const user = { name: "Ada" };
const alias = user;
alias.name = "Bea";
console.log(user.name); // "Bea" — same object

function rename(obj) {
  obj.name = "Cara";   // mutates the caller's object
  obj = { name: "Dee" }; // rebinding does not
}
rename(user);
console.log(user.name); // "Cara"

Q52 of 311 · Language fundamentals

typeof operator

What does typeof return?

A string tag: "undefined", "boolean", "number", "bigint", "string", "symbol", "function", or "object". Arrays, null, and dates all say "object". Use Array.isArray, value === null, and instanceof Date for finer tests. typeof undeclaredVariable is "undefined" without throwing — unusual compared to other operators.

Examples

JavaScript
typeof [];            // "object"
Array.isArray([]);    // true
typeof null;          // "object"
null === null;        // true — check null this way
typeof new Date();    // "object"
new Date() instanceof Date; // true

typeof notDeclared;   // "undefined" (does not throw)

Q53 of 311 · Language fundamentals

null vs undefined

When do you use null vs undefined?

undefined means a value was never set: missing args, missing properties, uninitialized let. null is an intentional empty object value you assign. JSON has null, not undefined — stringify omits undefined keys. APIs should pick one empty value and stick to it.

Examples

JavaScript
let score;                 // undefined
const user = { city: null }; // intentional empty

function greet(name) {
  return name ?? "friend";
}
greet();          // "friend"
greet(undefined); // "friend"
greet(null);      // "friend"
greet("");        // ""

JSON.stringify({ a: undefined, b: null }); // '{"b":null}'

Q54 of 311 · Language fundamentals

var, let, and const

What is the difference between var, let, and const?

var is function-scoped, hoisted, and can be redeclared. let and const are block-scoped and live in the temporal dead zone until initialized. const cannot be reassigned but object properties can still change. Prefer const, then let; avoid var in new code.

Examples

JavaScript
function demo() {
  if (true) {
    var hidden = 1;
    let block = 2;
    const frozen = 3;
  }
  console.log(hidden); // 1 — function scoped
  // console.log(block); // ReferenceError
}

const user = { name: "Ada" };
user.name = "Bea";     // ok — mutation
// user = {};          // TypeError — reassignment

Q55 of 311 · Language fundamentals

Hoisting

What is hoisting?

Declarations are processed before step-by-step execution. Function declarations are hoisted with their body. var is hoisted as undefined. let/const are hoisted but uninitialized (TDZ). Function expressions assigned to const are not callable before that line. Interviewers love: console.log(a); var a = 1;

Examples

JavaScript
console.log(a); // undefined
var a = 1;

console.log(add(2, 3)); // 5 — declaration is hoisted
function add(x, y) {
  return x + y;
}

// console.log(n); // ReferenceError (TDZ)
let n = 10;

// double(2); // TypeError: double is not a function
const double = function (x) {
  return x * 2;
};

Q56 of 311 · Language fundamentals

Temporal dead zone

What is the temporal dead zone?

The span from the start of a block until a let/const (or class) is initialized. Accessing the name in that span throws ReferenceError. It prevents accidental use-before-define that var allowed with undefined.

Examples

JavaScript
{
  // console.log(count); // ReferenceError: cannot access before initialization
  let count = 0;
  console.log(count); // 0
}

console.log(typeof missing); // "undefined" — undeclared
{
  // console.log(typeof boxed); // ReferenceError — TDZ, not undeclared
  let boxed = 1;
}

Q57 of 311 · Language fundamentals

=== vs ==

Why prefer === over ==?

== coerces types using abstract equality ("5" == 5 is true, null == undefined is true). === is SameValueX (no coercion) except it treats +0 and -0 as equal and NaN !== NaN. Object.is handles NaN and zeros more precisely. Default to ===.

Examples

JavaScript
5 == "5";   // true  — coerced
5 === "5";  // false — different types

null == undefined;  // true
null === undefined; // false

NaN === NaN;        // false
Object.is(NaN, NaN); // true
Object.is(0, -0);    // false
0 === -0;            // true

Q58 of 311 · Language fundamentals

Type coercion

What is type coercion? Give examples.

JS converts values when operators need another type. + prefers strings if either side is a string ("2"+2 → "22"). Other arithmetic prefers numbers ("2"*3 → 6). Boolean context uses truthiness. Explicit conversion: Number, String, Boolean, Boolean(x) or !!x.

Example

JavaScript
"2" + 2;   // "22"
"2" * 3;   // 6
true + 1;  // 2
Number("08"); // 8
Number("10px"); // NaN
Boolean("");  // false
!!"Ada";      // true

Q59 of 311 · Language fundamentals

Truthy and falsy

Which values are falsy?

false, 0, -0, 0n, "", null, undefined, NaN. Everything else is truthy, including [], {}, "0", and new Boolean(false) (an object). Never use if (arr) to test emptiness — check length.

Examples

JavaScript
Boolean(0);          // false
Boolean("");         // false
Boolean(null);       // false
Boolean([]);         // true
Boolean("0");        // true
Boolean(new Boolean(false)); // true — it's an object

const items = [];
if (items) console.log("runs even when empty");
if (items.length) console.log("use length instead");

Q60 of 311 · Language fundamentals

NaN

What is NaN and how do you detect it?

NaN means “not a number” — failed numeric conversion or invalid math. NaN !== NaN, so use Number.isNaN(x). Global isNaN coerces first (isNaN("foo") is true). Number.isFinite is the twin for real numbers.

Example

JavaScript
Number("oops");     // NaN
0 / 0;              // NaN
NaN === NaN;        // false
Number.isNaN(NaN);  // true
Number.isNaN("foo"); // false
isNaN("foo");        // true — coerces first
Number.isFinite(10); // true
Number.isFinite(NaN); // false

Q61 of 311 · Language fundamentals

Infinity

When do you get Infinity?

Overflow (1/0, Number.MAX_VALUE * 2) or division by 0. Number.isFinite(x) is false for Infinity. JSON.stringify(Infinity) becomes null. Avoid relying on Infinity as a sentinel unless the team agrees.

Examples

JavaScript
1 / 0;                    // Infinity
-1 / 0;                   // -Infinity
Number.isFinite(1 / 0);   // false
JSON.stringify(Infinity); // "null"

let best = -Infinity;
for (const n of [3, 9, 2]) best = Math.max(best, n);
console.log(best); // 9

Q62 of 311 · Language fundamentals

Pass by value or reference?

Are arguments passed by value or reference?

Everything is pass-by-value, but the value of an object is a reference. Reassigning a parameter does nothing to the caller. Mutating a property of an object argument is visible to the caller. This wording scores well in interviews.

Examples

JavaScript
function bumpNumber(n) {
  n = n + 1;
}
let score = 10;
bumpNumber(score);
console.log(score); // 10 — primitive copy

function bumpUser(user) {
  user.score += 1;
}
const player = { score: 10 };
bumpUser(player);
console.log(player.score); // 11 — same object, mutated

function replaceUser(user) {
  user = { score: 0 };
}
replaceUser(player);
console.log(player.score); // 11 — reassignment stayed local

Q63 of 311 · Language fundamentals

Immutability

How do you keep data immutable?

Do not mutate; return new objects/arrays (spread, map, filter). Object.freeze is shallow. structuredClone or spread nested layers for copies. Immutability makes undo, React state, and debugging easier.

Examples

JavaScript
const original = { user: { name: "Ada" }, tags: ["js"] };

// new object, same nested refs (shallow)
const shallow = { ...original, tags: [...original.tags, "css"] };

// deep copy of data
const deep = structuredClone(original);
deep.user.name = "Bea";
console.log(original.user.name); // "Ada"

const frozen = Object.freeze({ n: 1, nested: { n: 2 } });
// frozen.n = 5;           // throws in strict mode
frozen.nested.n = 9;       // still mutates — freeze is shallow

Q64 of 311 · Language fundamentals

Strict mode

What does "use strict" change?

It forbids accidental globals, makes this undefined in bare function calls, turns some silent errors into throws (assigning to non-writable), and blocks with and octal tricks. ES modules and classes are strict by default.

Examples

JavaScript
"use strict";

function demo() {
  // x = 1; // ReferenceError — no accidental global
  console.log(this); // undefined, not window
}

const obj = {};
Object.defineProperty(obj, "id", { value: 1, writable: false });
// obj.id = 2; // TypeError in strict mode (silent fail in sloppy)

demo();

Q65 of 311 · Language fundamentals

Global object

What is the global object?

window in browsers, global in Node, globalThis everywhere. It holds setTimeout, JSON, Math, and (in browsers) document. Avoid adding your own globals. globalThis is the interview-safe name.

Examples

JavaScript
globalThis.setTimeout; // works in browser and Node
globalThis.JSON.stringify({ ok: true });

// avoid this:
// window.appData = {};

const app = { version: 1 }; // keep your state in a module instead

Q66 of 311 · Language fundamentals

Template literals

What are template literals?

Backtick strings with ${expression} interpolation and multi-line text. Tagged templates (css`...` or String.raw) receive the raw parts and values — used by styled-components and GraphQL.

Examples

JavaScript
const name = "Ada";
const score = 12;
const msg = `Hello, ${name}. Score: ${score}`;
// "Hello, Ada. Score: 12"

const html = `
<ul>
  <li>${name}</li>
</ul>
`;

console.log(String.raw`C:\temp\file`); // keeps backslashes

Q67 of 311 · Language fundamentals

The + operator

Why is + special?

If either operand is a string, + concatenates after ToString. Otherwise it adds numbers (ToNumber). []+{} is a famous trap. Use Number() or unary + when you mean math.

Example

JavaScript
"2" + 2;     // "22"
2 + 2;       // 4
+"2" + 2;    // 4
Number("2") + 2; // 4
[] + {};     // "[object Object]"
true + true; // 2

Q68 of 311 · Language fundamentals

Optional chaining

What does ?. do?

user?.address?.city short-circuits to undefined if anything on the left is nullish. Also works for calls fn?.() and indexes obj?.[key]. It does not replace defaults — pair with ??.

Examples

JavaScript
const user = { profile: { city: "Pune" } };
user.profile?.city;     // "Pune"
user.address?.city;     // undefined — no throw
user.save?.();          // undefined if save missing
user.tags?.[0];         // undefined

const city = user.address?.city ?? "Unknown";

Q69 of 311 · Language fundamentals

Nullish coalescing

?? vs || ?

?? returns the right side only for null or undefined. || also treats 0, "", and false as missing. Prefer ?? for defaulting numbers and strings that can be empty-but-valid.

Examples

JavaScript
0 || 10;   // 10 — 0 is falsy
0 ?? 10;   // 0  — 0 is not nullish
"" || "n/a"; // "n/a"
"" ?? "n/a"; // ""

const page = 0;
const current = page ?? 1; // 0
const fallback = page || 1; // 1 — wrong if 0 is valid

Q70 of 311 · Language fundamentals

&& and || short-circuit

How do && and || work as expressions?

|| returns the first truthy value (or the last). && returns the first falsy (or the last). They stop evaluating once the result is known — useful for cond && doWork() but optional chaining is clearer for property access.

Examples

JavaScript
const name = "" || "guest"; // "guest"
const first = "Ada" && "Lovelace"; // "Lovelace"

const user = { admin: true };
user.admin && console.log("show admin tools");

const settings = { volume: 0 };
settings.volume || 5;  // 5 — bug if 0 is allowed
settings.volume ?? 5;  // 0

Q71 of 311 · Language fundamentals

switch statements

What should you remember about switch?

It uses === comparison. Cases fall through without break. You can switch(true) with case expr, but if/else is often clearer. Default handles unmatched values.

Examples

JavaScript
function label(status) {
  switch (status) {
    case "ok":
      return "All good";
    case "warn":
    case "info":
      return "Check logs"; // fall-through
    default:
      return "Unknown";
  }
}

label("warn"); // "Check logs"
label("nope"); // "Unknown"

Q72 of 311 · Language fundamentals

for, for...of, for...in, forEach

When do you use each loop?

for is index control. for...of walks iterable values (arrays, strings, maps). for...in walks enumerable keys including inherited — rarely what you want for arrays. forEach cannot break/await easily. Use for...of with await in async loops.

Examples

JavaScript
const nums = [10, 20, 30];

for (let i = 0; i < nums.length; i++) console.log(i, nums[i]);

for (const n of nums) console.log(n);        // values
for (const key in nums) console.log(key);    // "0" "1" "2" (keys)

nums.forEach((n) => console.log(n));
// cannot break or await inside forEach easily

Q73 of 311 · Language fundamentals

break and continue

What do break and continue do?

break leaves the loop (or switch). continue skips the rest of this iteration. Labels exist for nested loops but are uncommon. forEach cannot break — use some/every/for.

Examples

JavaScript
for (let i = 0; i < 5; i++) {
  if (i === 1) continue; // skip 1
  if (i === 4) break;    // stop before 4
  console.log(i);
}
// 0 2 3

const nums = [1, 2, 9, 3];
const hasBig = nums.some((n) => n > 5); // true — stops early

Q74 of 311 · Language fundamentals

Floating-point precision

Why is 0.1 + 0.2 !== 0.3?

IEEE-754 binary floats cannot represent some decimals exactly. Compare with a tolerance, or use integers (cents) or libraries for money. toFixed returns a string. Number.EPSILON is the usual delta.

Examples

JavaScript
0.1 + 0.2;            // 0.30000000000000004
0.1 + 0.2 === 0.3;     // false
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON; // true

const cents = 10 + 20; // store money as integers
(cents / 100).toFixed(2); // "0.30" (string)

Q75 of 311 · Language fundamentals

parseInt and Number

parseInt("08") vs Number("08")?

parseInt reads until a non-digit and takes a radix (always pass 10). Number() / unary + parse the whole string or yield NaN. parseInt("10px") is 10; Number("10px") is NaN.

Example

JavaScript
parseInt("08", 10);  // 8
parseInt("10px", 10); // 10
Number("08");         // 8
Number("10px");       // NaN
+"08";                // 8
parseInt("08");       // 8 in modern JS — still pass 10

Q76 of 311 · Language fundamentals

Math.random

Is Math.random good for security?

No. It is not cryptographically strong. Use crypto.getRandomValues for tokens. Math.random is fine for games and shuffles that are not security-sensitive.

Examples

JavaScript
Math.floor(Math.random() * 10); // 0..9 for a game

const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes); // tokens / session ids

Q77 of 311 · Language fundamentals

Are strings mutable?

Are strings mutable?

No. Methods return new strings. Concatenation in a tight loop can be costly; arrays of parts then join is the usual pattern. Indexes str[0] cannot assign in strict mode.

Examples

JavaScript
let s = "hi";
s[0] = "H";
console.log(s); // "hi" — unchanged

s = s.toUpperCase();
console.log(s); // "HI"

const parts = ["Hello", " ", "Ada"];
parts.join(""); // cheaper than += in a hot loop

Q78 of 311 · Language fundamentals

Automatic semicolon insertion

When do missing semicolons break?

ASI inserts ; before a newline in some cases. Starting a line with ( [ ` or + can glue to the previous line. return\nvalue returns undefined. Many teams use semicolons or a formatter (Prettier) to avoid ASI bugs.

Examples

JavaScript
const n = 1
const m = 2  // ok here

const fn = () => {
  return
  { ok: true }
};
fn(); // undefined — ASI after return

const obj = { n: 1 }
;[1, 2].forEach(console.log) // leading ; protects the [

Q79 of 311 · Language fundamentals

Error types

Name common Error types.

Error, TypeError, ReferenceError, SyntaxError, RangeError. Custom errors extend Error and set name. throw can throw anything, but throwing Error objects keeps stacks.

Examples

JavaScript
throw new TypeError("Need a number");

class AppError extends Error {
  constructor(message) {
    super(message);
    this.name = "AppError";
  }
}

try {
  JSON.parse("{");
} catch (err) {
  console.log(err instanceof SyntaxError); // true
}

Q80 of 311 · Language fundamentals

try/catch/finally

Does finally always run?

Yes, even after return in try/catch — finally can override the return value if it also returns. catch binds the error. Optional catch binding: catch { }. Use try around the smallest region that can fail.

Examples

JavaScript
function parse(json) {
  try {
    return JSON.parse(json);
  } catch (err) {
    return null;
  } finally {
    console.log("attempt finished");
  }
}

parse('{"a":1}'); // { a: 1 }
parse("{");       // null

Q81 of 311 · Language fundamentals

JSON.stringify / parse

What does JSON drop?

undefined, functions, and symbols vanish. Dates become ISO strings. NaN/Infinity become null. toJSON can customize. parse reviver can revive dates. Circular objects throw.

Examples

JavaScript
const user = {
  name: "Ada",
  skip: undefined,
  when: new Date("2024-01-01"),
  greet() {},
};
JSON.stringify(user);
// '{"name":"Ada","when":"2024-01-01T00:00:00.000Z"}'

JSON.parse('{"n":1}', (key, value) => value);

Q82 of 311 · Language fundamentals

JavaScript Date

What is tricky about Date?

Months are 0-based. Date.parse is implementation-defined for non-ISO strings. Dates are mutable. Prefer ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ). Temporal is the upcoming replacement. new Date() is local; Date.now() is a number.

Examples

JavaScript
new Date(2024, 0, 5); // 5 Jan 2024 — month 0
Date.parse("2024-01-05T00:00:00.000Z"); // reliable ISO

const d = new Date("2024-01-05T00:00:00Z");
d.toISOString();
Date.now(); // number of ms

Q83 of 311 · Language fundamentals

setTimeout(fn, 0)

What does a 0ms timeout do?

It schedules fn on the macrotask queue after the current stack — not immediately. Browsers may clamp nested timeouts. Use it to yield to paint or wait until after events.

Example

JavaScript
console.log("A");
setTimeout(() => console.log("C"), 0);
Promise.resolve().then(() => console.log("B"));
console.log("D");
// A D B C  — timeout is a later macrotask

Q84 of 311 · Language fundamentals

IIFE

What is an IIFE?

(function(){ ... })() or (() => { ... })() runs immediately and creates a scope. Used before modules/let to avoid globals and to capture loop variables in old var code.

Examples

JavaScript
const counter = (() => {
  let n = 0;
  return {
    inc() {
      n += 1;
      return n;
    },
  };
})();

counter.inc(); // 1
counter.inc(); // 2

Q85 of 311 · Language fundamentals

ES modules vs CommonJS

import vs require?

ESM is static, async, and lives in files with import/export; this is undefined at top level in modules. CJS require is sync and dynamic, module.exports. Mixing them in Node needs care (.mjs, "type":"module").

Examples

JavaScript
// math.js
export const add = (a, b) => a + b;
export default function area(w, h) {
  return w * h;
}

// app.js
import area, { add } from "./math.js";
add(2, 3);
area(4, 5);

// CommonJS
// const { add } = require("./math");

Q86 of 311 · Language fundamentals

Default parameters

When do defaults apply?

Only when the argument is undefined (not null, not 0). Defaults can use earlier parameters. They are evaluated at call time, so default = [] creates a new array each call — good.

Examples

JavaScript
function greet(name = "friend", times = 1) {
  return Array(times).fill(`Hi ${name}`).join(", ");
}
greet();           // "Hi friend"
greet("Ada");      // "Hi Ada"
greet(undefined, 2); // "Hi friend, Hi friend"
greet(null);       // "Hi null" — null is not replaced

function push(item, list = []) {
  list.push(item);
  return list;
}
push("a"); // ["a"]
push("b"); // ["b"] — new array each call

Q87 of 311 · Language fundamentals

Rest vs spread

What is the difference?

Rest collects (...args) in functions or [...rest] in destructuring. Spread expands [...arr], { ...obj }, or fn(...arr). They look the same (...) but one packs and one unpacks.

Examples

JavaScript
function sum(...nums) {        // rest: pack
  return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3); // 6

const more = [3, 4];
const all = [1, 2, ...more];   // spread: unpack
Math.max(...all);

const user = { name: "Ada", age: 30 };
const copy = { ...user, age: 31 };

Q88 of 311 · Language fundamentals

Destructuring

Show object and array destructuring.

const { name, age = 0 } = user; const [first, ...rest] = arr; Nested destructuring works. Swap: [a,b]=[b,a]. Function params can destructure. Defaults apply when the value is undefined.

Examples

JavaScript
const user = { name: "Ada", city: "Pune" };
const { name, city: town = "N/A" } = user;

const pair = [10, 20, 30];
const [first, , third] = pair;

let a = 1;
let b = 2;
[a, b] = [b, a];

function print({ name }) {
  console.log(name);
}
print(user);

Q89 of 311 · Language fundamentals

freeze, seal, preventExtensions

Compare Object.freeze, seal, preventExtensions.

preventExtensions: no new keys. seal: that plus no delete, keys stay configurable:false. freeze: that plus values cannot be assigned (shallow). All are shallow. Use them to catch mutations, not as a security boundary.

Examples

JavaScript
const frozen = Object.freeze({ n: 1, nested: { n: 2 } });
// frozen.n = 5;        // TypeError in strict
frozen.nested.n = 9;    // still works — shallow

const sealed = Object.seal({ n: 1 });
sealed.n = 2;           // ok
// delete sealed.n;     // fails when sealed

const locked = Object.preventExtensions({ n: 1 });
// locked.m = 2;        // cannot add keys

Q90 of 311 · Language fundamentals

in vs hasOwnProperty

How do you test if a key exists?

key in obj includes the prototype chain. Object.hasOwn(obj, key) (or hasOwnProperty.call) is own keys only. obj.key !== undefined misses keys that exist with value undefined.

Example

JavaScript
const user = { name: "Ada", age: undefined };
"name" in user;                 // true
"age" in user;                  // true
"toString" in user;             // true — inherited
Object.hasOwn(user, "toString"); // false
user.age !== undefined;         // false — misses existing undefined

Q91 of 311 · Language fundamentals

Why is for...in risky on arrays?

Why is for...in risky on arrays?

It walks enumerable keys as strings, including inherited enumerable properties, and order is not guaranteed the same as index order historically. Use for...of, forEach, or a C-style for for arrays.

Examples

JavaScript
const nums = [10, 20];
nums.extra = "nope";

for (const key in nums) {
  console.log(key, nums[key]); // "0" "1" "extra"
}

for (const n of nums) {
  console.log(n); // 10 20
}

Q92 of 311 · Language fundamentals

Array.isArray

Why not instanceof Array?

Array.isArray works across realms (iframes, vm). instanceof Array can fail if the array came from another window. Always prefer Array.isArray.

Examples

JavaScript
Array.isArray([]);     // true
Array.isArray({});     // false
[] instanceof Array;   // true here, may fail across iframes

function takeList(value) {
  if (!Array.isArray(value)) throw new TypeError("Expected array");
  return value.length;
}

Q93 of 311 · Language fundamentals

void operator

What is void 0?

void expr evaluates expr and returns undefined. void 0 is a safe undefined (in old code people could overwrite undefined). Used in IIFE bookmarks and some minified code.

Examples

JavaScript
void 0;              // undefined
void (function () { console.log("runs"); })();

const button = {
  href: "javascript:void(0)", // old pattern: click without navigation
};

Q94 of 311 · Language fundamentals

Comma operator

What does (a, b) mean?

Evaluate a, then b, result is b. Rarely useful in production; shows up in minifiers and for loops: for (let i = 0, j = n; i < j; i++, j--).

Examples

JavaScript
let x = (console.log("first"), 42);
console.log(x); // 42

for (let i = 0, j = 3; i < j; i++, j--) {
  console.log(i, j);
}
// 0 3
// 1 2

Q95 of 311 · Language fundamentals

Bitwise operators in JS

Why do people use n | 0?

Bitwise ops convert to 32-bit integers. | 0 or ~~ truncates toward 0. >>> 0 makes unsigned 32-bit. Fine for tricks, confusing for money and large integers — prefer Math.trunc / Math.floor.

Examples

JavaScript
7.9 | 0;     // 7  — truncate toward 0
~~7.9;       // 7
(-7.9) | 0;  // -7

Math.trunc(7.9);  // 7 — clearer
(1 << 3);         // 8

Q96 of 311 · Language fundamentals

Unicode in JS strings

Why is '👍'.length 2?

JS strings are UTF-16 code units. Many emoji are surrogate pairs (length 2). Use [...str].length or Array.from for code points. Graphemes need Intl.Segmenter.

Example

JavaScript
"👍".length;           // 2
[..."👍"].length;      // 1
Array.from("👍").length; // 1
"👍".codePointAt(0).toString(16); // "1f44d"

Q97 of 311 · Language fundamentals

BigInt

When do you use BigInt?

Integers bigger than Number.MAX_SAFE_INTEGER (2^53-1). Write 10n. You cannot mix Number and BigInt in arithmetic without converting. JSON.stringify does not support BigInt by default.

Examples

JavaScript
Number.MAX_SAFE_INTEGER; // 9007199254740991
9007199254740991 + 2;    // 9007199254740992 — precision lost
9007199254740991n + 2n;  // 9007199254740993n

// 1n + 1; // TypeError — mix Number and BigInt
Number(1n) + 1; // 2

Q98 of 311 · Language fundamentals

Symbol

What are symbols for?

Unique, non-string keys. Symbol('id') !== Symbol('id'). Well-known symbols customize iteration (Symbol.iterator), conversion (toPrimitive), etc. They are omitted from JSON and most key listings unless you ask getOwnPropertySymbols.

Examples

JavaScript
const id = Symbol("id");
const user = { name: "Ada", [id]: 7 };
user[id]; // 7
Object.keys(user); // ["name"]
JSON.stringify(user); // '{"name":"Ada"}'

Symbol("id") === Symbol("id"); // false

Q232 of 311 · Language fundamentals

let inside switch

Why can let in a switch case throw?

The whole switch is one block. Two case clauses declaring the same let collide. Wrap each case in { } so each has its own block, or use different names. A favorite TDZ / duplicate-binding question.

Q233 of 311 · Language fundamentals

Why is it called let?

Where does the name let come from?

From mathematics: “let x be …”. It is a block binding, not a hint that the value will change (that is let vs const). var was the old function-scoped binding.

Q234 of 311 · Language fundamentals

Double bang !!

What does !!value do?

It coerces to a real boolean: !x is boolean, !!x flips back. Same as Boolean(x). Useful when an API must store true/false, not a truthy object. Prefer Boolean(x) in teaching code so the intent is obvious.

Q235 of 311 · Language fundamentals

delete operator

What does delete obj.key do?

Removes an own configurable property. Returns true if the property is gone or never existed; false if it could not be deleted (non-configurable). Does not affect variables (delete x is sloppy-mode weirdness). Prefer setting undefined or using a Map when keys come and go.

Q236 of 311 · Language fundamentals

Undeclared vs undefined

What is the difference?

Undeclared: no binding exists; reading it throws ReferenceError (except typeof). undefined: the binding exists and holds the undefined value. Assigning to an undeclared name in sloppy mode creates a global — strict mode throws.

Q237 of 311 · Language fundamentals

Global variables

Why are globals a problem?

Name clashes, hidden coupling, hard tests, and accidental window.foo in the browser. Modules and const/let at file scope replaced most IIFE+global patterns. In browsers, implicit globals from missing var/let are a classic bug.

Q238 of 311 · Language fundamentals

Number.isFinite

When do you use isFinite?

Number.isFinite(x) is true only for real finite numbers — not NaN, Infinity, or non-numbers. Global isFinite coerces first (isFinite("1") is true). Prefer Number.isFinite after you already have a number.

Q239 of 311 · Language fundamentals

Unary plus and minus

What does +value do?

Unary + runs ToNumber: +"42" is 42, +true is 1, +[] is 0, +{} is NaN. Unary minus negates after ToNumber. Prefer Number(value) at API boundaries so the coercion is named.

Q240 of 311 · Language fundamentals

Conditional (ternary) operator

What is a ? b : c ?

An expression that picks b if a is truthy, else c. You can nest them; readability dies after one nest — use if or a lookup. It is not a statement; both branches should be values, not long blocks.

Q242 of 311 · Language fundamentals

Compiled or interpreted?

Is JavaScript compiled or interpreted?

Engines parse, then JIT-compile hot code (V8, SpiderMonkey). You still ship source (or bundled JS), not a binary you compiled yourself. “Interpreted” is the old one-line answer; “parsed then JIT” is the better one.

Q243 of 311 · Language fundamentals

Case sensitivity

Is JavaScript case-sensitive?

Yes. name and Name are different bindings. HTML attribute names are not; the DOM maps them. JSON keys are case-sensitive strings.

Q244 of 311 · Language fundamentals

Java vs JavaScript

Are they related?

No shared lineage. The name was marketing in the 1990s. Java is statically typed and class-based; JavaScript is a different language with prototypes, a single-threaded event loop, and first-class functions.

Q245 of 311 · Language fundamentals

Who created JavaScript?

Who created JavaScript, and what is ECMAScript?

Brendan Eich at Netscape (1995). ECMAScript is the standard (TC39 / ECMA-262) that JS engines implement. “ES6” is ES2015. Browser APIs (DOM, fetch) are not the language standard — they are host APIs.

Q246 of 311 · Language fundamentals

JSON syntax rules

What is valid JSON?

Double-quoted keys and strings only. No comments, no undefined, no functions, no trailing commas, no NaN/Infinity. Arrays and objects nest. JSON.parse rejects the rest. JSON is a data format, not JavaScript source.

Q276 of 311 · Language fundamentals

Debugging JavaScript

How do you debug JS?

Browser DevTools: breakpoints, debugger statement, step, call stack, watch. console.log / table / error. Source maps for bundled code. Node inspect. Network and Performance panels for fetch and jank. Reproduce with a failing test when you can.

Q277 of 311 · Language fundamentals

debugger

What does the debugger statement do?

Pauses if DevTools is open, like a breakpoint. Strip or guard it before production. Breakpoints in the Sources panel are better for ongoing work because they are not committed.

Q278 of 311 · Language fundamentals

Native, host, and user objects

What is the difference?

Native: specified by ECMAScript (Object, Array, Date). Host: provided by the environment (window, document, Node Buffer). User: the objects your code creates. Host objects can have exotic behavior; do not assume they are ordinary maps.

Q287 of 311 · Language fundamentals

Labeled statements

What are JS labels?

outer: for (...) { continue outer } or break outer to jump out of nested loops. Valid, rarely needed, easy to abuse. Prefer a named function and return, or flatten the loop.

Q288 of 311 · Language fundamentals

Random integers

How do you get a random integer in a range?

Math.floor(Math.random() * (max - min + 1)) + min for inclusive integers. Not for security. crypto.getRandomValues for tokens. Watch off-by-one on the * n vs * (n+1) formula.

Q289 of 311 · Language fundamentals

Intl

What is the Intl object?

Standard internationalization: Intl.DateTimeFormat, NumberFormat, Collator, RelativeTimeFormat, Segmenter. Pass a locale ("en-IN") instead of rolling your own date strings. Time zones use the IANA name in DateTimeFormat options.

Q292 of 311 · Language fundamentals

Object.isFrozen / isSealed

How do you check freeze and seal?

Object.isFrozen(obj) / isSealed / isExtensible. Frozen implies sealed implies non-extensible. All shallow. Object.is(a, b) is value equality (NaN, -0), not freeze.

Q297 of 311 · Language fundamentals

Default values

How do you assign defaults?

Parameter defaults (fn, x = 1), destructuring ({ n = 0 } = {}), ?? for nullish, ||= for falsy (careful with 0). Do not use || for numbers that can be zero.

Q298 of 311 · Language fundamentals

Reserved words

Can you use class as a variable name?

No for bindings: class, return, const are reserved. You can use them as object keys (obj.class) and sometimes as properties after a dot. Strict mode reserved more names (public, interface historically). If it is awkward, pick another name.

Q299 of 311 · Language fundamentals

Error object

What is on an Error?

message, name, stack (non-standard but universal). Cause is newer (err.cause). Custom errors extend Error and set this.name. throw 5 works but loses a stack — throw new Error("…").

Q300 of 311 · Language fundamentals

SyntaxError

When do you get a SyntaxError?

The parser rejects the source: missing ), invalid JSON.parse input, unexpected token. It throws before that script runs. You cannot try/catch a SyntaxError in the same file; you can catch JSON.parse or eval.

Q305 of 311 · Language fundamentals

Why strict mode?

Why opt into strict mode?

Catch silent mistakes (misspelled assignment, this leaks to global). Modules and classes already are strict. "use strict" at the top of a script or function is for leftover sloppy files.

Q306 of 311 · Language fundamentals

Purpose of void 0

Why write void 0 instead of undefined?

In old sloppy scripts, undefined could be overwritten as a variable. void 0 always yields the real undefined. Today, const/let and modules make that moot — write undefined.

Q307 of 311 · Language fundamentals

Object.preventExtensions

What does preventExtensions do?

Blocks adding new own properties. Existing ones still assign and delete (unless sealed/frozen). Returns the object. Rare in app code; shows up in “compare freeze/seal/preventExtensions” interviews.

Q310 of 311 · Language fundamentals

Comparing dates

How do you compare two Date objects?

date.getTime() or Number(date) then compare numbers. < on Date objects works via valueOf but is easy to misread. Do not === two Date instances (different references). Prefer ISO strings or Temporal for calendar math.

Functions, scope & closures

Q99 of 311 · Functions, scope & closures

Function declaration vs expression

What is the difference?

Declarations are hoisted and can be called before their line. Expressions (const f = function(){} or arrows) are not callable before initialization. Named expressions help stack traces. Prefer declarations or const arrows at module scope for clarity.

Examples

JavaScript
sayHi(); // works — declaration hoisted
function sayHi() {
  return "hi";
}

// shout(); // TypeError
const shout = function shoutFn() {
  return "hey";
};

const add = (a, b) => a + b;

Q100 of 311 · Functions, scope & closures

Arrow functions

How do arrows differ from function?

No own this, arguments, super, or prototype. Cannot be constructors (new throws). this is lexical from the enclosing scope. Great for callbacks; bad for object methods that need their own this, or prototype methods.

Examples

JavaScript
const user = {
  name: "Ada",
  regular: function () {
    return this.name;
  },
  arrow: () => this.name,
};

user.regular(); // "Ada"
user.arrow();   // undefined (or global) — lexical this

const Button = {
  clicks: 0,
  bind() {
    setTimeout(() => {
      this.clicks += 1; // arrow keeps Button
    }, 0);
  },
};

Q101 of 311 · Functions, scope & closures

this

How is this determined?

In a function, this depends on the call site: obj.method() binds obj, fn() is undefined in strict mode (global object in sloppy), call/apply/bind set it, new sets the instance, arrows use lexical this. Event handlers bind the element unless you use an arrow.

Examples

JavaScript
const user = {
  name: "Ada",
  hi() {
    return this.name;
  },
};
user.hi(); // "Ada"

const hi = user.hi;
hi(); // undefined in strict mode — lost receiver

user.hi.call({ name: "Bea" }); // "Bea"

class Counter {
  n = 0;
  inc = () => {
    this.n += 1;
  };
}

Q102 of 311 · Functions, scope & closures

call, apply, and bind

Compare call, apply, and bind.

call(thisArg, a, b) invokes now. apply(thisArg, [a, b]) invokes now with an array of args (spread has mostly replaced apply). bind(thisArg, ...partial) returns a new function with this (and optional args) fixed. Arrows ignore bind’s this.

Examples

JavaScript
function greet(hi, punct) {
  return hi + " " + this.name + punct;
}
const ada = { name: "Ada" };

greet.call(ada, "Hello", "!");           // "Hello Ada!"
greet.apply(ada, ["Hello", "!"]);        // "Hello Ada!"
const bound = greet.bind(ada, "Hi");
bound(".");                              // "Hi Ada."

Q103 of 311 · Functions, scope & closures

Closures

What is a closure?

A function that remembers variables from the scope where it was created, even after that scope returned. Used for data privacy, partial application, and callbacks. The classic trap is var in a for loop sharing one i — use let or bind the value.

Examples

JavaScript
function makeCounter() {
  let n = 0;
  return function () {
    n += 1;
    return n;
  };
}
const next = makeCounter();
next(); // 1
next(); // 2

function secret(password) {
  return {
    check(guess) {
      return guess === password;
    },
  };
}
secret("abc").check("abc"); // true

Q104 of 311 · Functions, scope & closures

Closures in loops

Why do all timeouts print 3 with var?

var i is one function-scoped binding. Closures see the final i. let i creates a binding per iteration. Alternatively pass i into an IIFE. This is still a favorite interview question.

Examples

JavaScript
// broken with var
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}
// 3 3 3

for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 0);
}
// 0 1 2

for (var k = 0; k < 3; k++) {
  setTimeout((n) => console.log(n), 0, k);
}
// 0 1 2

Q105 of 311 · Functions, scope & closures

Scope types

What scopes exist in JS?

Global, function, block (let/const/class), module. Catch bindings are scoped to catch. eval and with (sloppy) create dynamic scope — avoid them. Inner scopes can read outer variables; outer cannot read inner.

Examples

JavaScript
const globalName = "app";

function outer() {
  const city = "Pune";
  if (true) {
    const inner = 1;
    console.log(city); // visible
  }
  // console.log(inner); // ReferenceError
}
outer();

Q106 of 311 · Functions, scope & closures

Lexical scope

What is lexical scope?

Where you write the function decides which names it can see, not where you call it. That is why closures work. Dynamic this is the exception people confuse with scope.

Example

JavaScript
const x = "outer";
function read() {
  return x; // looks where read was written
}
function run(fn) {
  const x = "inner";
  return fn();
}
run(read); // "outer" — not "inner"

Q107 of 311 · Functions, scope & closures

Higher-order functions

What is a higher-order function?

A function that takes functions as arguments or returns a function: map, filter, reduce, debounce, withRetry. They are the core of JS style. Keep the inner function pure when you can.

Examples

JavaScript
function withLogging(fn) {
  return function (...args) {
    console.log("call", args);
    return fn(...args);
  };
}
const add = (a, b) => a + b;
const loggedAdd = withLogging(add);
loggedAdd(2, 3); // logs then 5

[1, 2, 3].map((n) => n * 2); // map is higher-order

Q108 of 311 · Functions, scope & closures

Pure functions

What makes a function pure?

Same inputs → same output, no mutation of outside state, no I/O. Easier to test and memoize. In practice, many functions are “mostly pure” and isolate side effects at the edges.

Examples

JavaScript
function tax(price) {
  return price * 0.18; // pure
}

let total = 0;
function addToCart(price) {
  total += price; // impure — hidden mutation
}

tax(100); // always 18

Q109 of 311 · Functions, scope & closures

Recursion

When do you recurse in JS?

Tree/DOM walks, flatten, factorial. Always a base case. Deep recursion can overflow the stack — prefer loops or trampolines for huge n. Tail-call optimization is not widely implemented in JS engines.

Examples

JavaScript
function factorial(n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}
factorial(5); // 120

function sumTree(node) {
  if (!node) return 0;
  return node.value + sumTree(node.left) + sumTree(node.right);
}

Q110 of 311 · Functions, scope & closures

arguments object

What is arguments?

Array-like object of params in non-arrow functions. Not a real array (no map unless you Array.from it). Rest parameters ...args are the modern replacement and work in arrows.

Examples

JavaScript
function oldSum() {
  return Array.from(arguments).reduce((a, b) => a + b, 0);
}
oldSum(1, 2, 3); // 6

const newSum = (...nums) => nums.reduce((a, b) => a + b, 0);
newSum(1, 2, 3); // 6

Q111 of 311 · Functions, scope & closures

Named parameters

How do you fake named params?

Pass one object and destructure: function createUser({ name, age = 0 }) {}. Defaults and extra keys work well. This is idiomatic in JS APIs.

Examples

JavaScript
function createUser({ name, age = 0, admin = false }) {
  return { name, age, admin };
}

createUser({ name: "Ada", admin: true });
// { name: "Ada", age: 0, admin: true }

Q112 of 311 · Functions, scope & closures

Generators

What is function* ?

A function that returns an iterator. yield pauses and returns a value; .next() resumes. Used for lazy sequences and (historically) async flow. for...of consumes them. async function* exists for streams.

Examples

JavaScript
function* ids() {
  let n = 1;
  while (true) yield n++;
}
const gen = ids();
gen.next().value; // 1
gen.next().value; // 2

function* range(from, to) {
  for (let i = from; i <= to; i++) yield i;
}
[...range(1, 3)]; // [1, 2, 3]

Q113 of 311 · Functions, scope & closures

Iterators and iterables

What makes an object iterable?

It has [Symbol.iterator]() returning an object with next() → { value, done }. Arrays, strings, maps, sets are iterable. You can spread and for...of them. Custom iterables show up in interviews as a plus.

Example

JavaScript
const countdown = {
  from: 3,
  [Symbol.iterator]() {
    let n = this.from;
    return {
      next() {
        if (n < 1) return { done: true, value: undefined };
        return { done: false, value: n-- };
      },
    };
  },
};
[...countdown]; // [3, 2, 1]

Q114 of 311 · Functions, scope & closures

What does new do?

What does new do?

Creates a new object, sets its prototype to Fn.prototype, binds this to that object, runs Fn, returns this unless the function returns another object. new arrow throws. Forgetting new on a constructor pollutes global this in sloppy mode.

Examples

JavaScript
function User(name) {
  this.name = name;
}
User.prototype.hi = function () {
  return "Hi " + this.name;
};

const ada = new User("Ada");
ada.hi(); // "Hi Ada"
ada instanceof User; // true

// User("Ada"); // sloppy mode: pollutes global this

Q115 of 311 · Functions, scope & closures

Constructor functions

How did JS do classes before class?

function User(name){ this.name = name } then User.prototype.greet = function(){...}. class is sugar over this model with stricter defaults. Know both — interviews still ask prototypes.

Examples

JavaScript
function Car(make) {
  this.make = make;
}
Car.prototype.honk = function () {
  return this.make + " beep";
};

const car = new Car("Tata");
car.honk(); // "Tata beep"
Object.getPrototypeOf(car) === Car.prototype; // true

Q116 of 311 · Functions, scope & closures

First-class functions

What does first-class mean?

Functions are values: store them in variables, pass them, return them, put them in arrays. That is why callbacks and promises work. JS treats functions as objects (they can have properties).

Example

JavaScript
const ops = {
  add: (a, b) => a + b,
  mul: (a, b) => a * b,
};
function run(fn, a, b) {
  return fn(a, b);
}
run(ops.add, 2, 3); // 5
[ops.add, ops.mul].map((fn) => fn(2, 3));

Q117 of 311 · Functions, scope & closures

Anonymous vs named functions

Should callbacks be named?

Names appear in stack traces and allow recursion. Anonymous arrows are fine for tiny map callbacks. For anything you debug, a name helps.

Examples

JavaScript
setTimeout(function tick() {
  console.log("named — easier stack traces");
}, 0);

[1, 2, 3].map(function double(n) {
  return n * 2;
});

Q118 of 311 · Functions, scope & closures

function.length

What is fn.length?

The count of declared parameters before the first default, rest, or some destructuring cases. curry implementations use it. It is not the count of arguments actually passed — that is arguments.length or rest.length.

Examples

JavaScript
function add(a, b, c = 0, ...rest) {}
add.length; // 2 — stops before default / rest

function curry(fn) {
  return (...args) =>
    args.length >= fn.length ? fn(...args) : curry(fn.bind(null, ...args));
}

Q119 of 311 · Functions, scope & closures

Methods extracted from objects

Why does const f = obj.method; f() lose this?

The call site is a bare f(), so this is undefined/global. Use obj.method() or const f = obj.method.bind(obj) or wrap () => obj.method(). A very common React class-component bug historically.

Examples

JavaScript
const user = {
  name: "Ada",
  hi() {
    return this.name;
  },
};

const hi = user.hi;
hi(); // undefined in strict mode

const bound = user.hi.bind(user);
bound(); // "Ada"
button.addEventListener?.("click", () => user.hi());

Q120 of 311 · Functions, scope & closures

Partial application

How is it different from curry?

Partial application fixes some arguments now and returns a function that takes the rest (bind does this). Currying is a series of unary functions. People mix the words — defining them clearly is the point.

Examples

JavaScript
function greet(hi, name) {
  return hi + " " + name;
}
const sayHi = greet.bind(null, "Hi");
sayHi("Ada"); // "Hi Ada"

const multiply = (a, b, c) => a * b * c;
const double = multiply.bind(null, 2);
double(3, 4); // 24

Q121 of 311 · Functions, scope & closures

Compose / pipe

What is function composition?

compose(f,g)(x) is f(g(x)). pipe runs left to right. Useful in data-transform pipelines. Implement with reduce. Keep functions unary when composing.

Examples

JavaScript
const compose = (f, g) => (x) => f(g(x));
const pipe = (...fns) => (x) => fns.reduce((v, fn) => fn(v), x);

const trim = (s) => s.trim();
const upper = (s) => s.toUpperCase();
compose(upper, trim)("  ada "); // "ADA"
pipe(trim, upper)("  ada ");    // "ADA"

Q122 of 311 · Functions, scope & closures

Side effects

What counts as a side effect?

Anything besides returning a value: DOM writes, fetch, logging, mutating args, Date.now(). Interviews like you to separate calculation from effects.

Examples

JavaScript
function total(prices) {
  return prices.reduce((a, b) => a + b, 0); // calculation
}

function saveTotal(prices) {
  localStorage.setItem("total", String(total(prices))); // effect
}

Q123 of 311 · Functions, scope & closures

Call stack vs heap

Where do closures live?

The call stack holds frames for running functions. Closed-over variables live on the heap as long as a closure references them — that can look like a memory leak if you keep callbacks forever.

Example

JavaScript
function outer() {
  const big = new Array(1e6).fill("x");
  return function inner() {
    return big.length; // keeps `big` alive on the heap
  };
}
const leak = outer();
leak();

Q228 of 311 · Functions, scope & closures

Unary function

What is a unary function?

A function of one argument. map(parseInt) is a classic bug because parseInt is not unary in the way map calls it (it also gets the index). Unary wrappers like Number or (x) => parseInt(x, 10) fix that. Currying aims at unary steps.

Q229 of 311 · Functions, scope & closures

First-order function

What is a first-order function?

A function that does not take or return other functions — the opposite of higher-order. Interviewers use the term to contrast with map/filter. Everyday helpers like add(a, b) are first-order.

Q230 of 311 · Functions, scope & closures

Functions are objects

Can a function have properties?

Yes. Functions are objects: fn.cache = {}, fn.help = "...". That is how jQuery plugins and memoize caches used to hang data on the function. Prefer a closure or WeakMap when the data should not be public.

Q231 of 311 · Functions, scope & closures

Missing function arguments

What happens if you pass too few or too many args?

Too few: the rest are undefined (defaults may apply). Too many: extras are ignored unless you use rest. arguments / rest still see them. JS does not throw on arity mismatch.

Q301 of 311 · Functions, scope & closures

Why pure functions?

What are the benefits of pure functions?

Easy tests, safe memoization, time-travel debugging, fewer race bugs. You still need impure edges (DOM, network). Interviews want you to name the trade: purity vs the real world’s I/O.

Objects, this & prototypes

Q124 of 311 · Objects, this & prototypes

Prototype chain

How does property lookup work?

If the object does not have an own property, JS looks at [[Prototype]] (obj.__proto__ / Object.getPrototypeOf), then that object’s prototype, until null. That is how methods on Array.prototype work for every array.

Examples

JavaScript
const arr = [1, 2];
arr.map; // found on Array.prototype
arr.toString; // found on Object.prototype

Object.getPrototypeOf(arr) === Array.prototype; // true
Object.getPrototypeOf(Array.prototype) === Object.prototype; // true

Q125 of 311 · Objects, this & prototypes

__proto__ vs prototype

What is the difference?

Fn.prototype is the object that will become the [[Prototype]] of instances created with new Fn. obj.__proto__ (legacy getter) is that instance’s prototype. Use Object.getPrototypeOf / setPrototypeOf. class uses the same machinery.

Examples

JavaScript
function User(name) {
  this.name = name;
}
const ada = new User("Ada");

User.prototype;                 // blueprint for instances
Object.getPrototypeOf(ada) === User.prototype; // true
ada.__proto__ === User.prototype; // legacy accessor

Q126 of 311 · Objects, this & prototypes

Object.create

What does Object.create(proto) do?

Makes a new object whose prototype is proto (or null). Useful for dictionaries without Object.prototype keys, and for inheritance without calling a constructor.

Examples

JavaScript
const proto = {
  hi() {
    return "Hi " + this.name;
  },
};
const ada = Object.create(proto);
ada.name = "Ada";
ada.hi(); // "Hi Ada"

const dict = Object.create(null);
dict.admin = true;
"toString" in dict; // false — no Object.prototype

Q127 of 311 · Objects, this & prototypes

Own vs inherited properties

How do you list keys?

Object.keys: enumerable own. Object.getOwnPropertyNames: own including non-enumerable (not symbols). getOwnPropertySymbols for symbols. for...in: enumerable own + inherited. Prefer Object.keys / Object.hasOwn in new code.

Example

JavaScript
const user = { name: "Ada" };
Object.keys(user);                    // ["name"]
Object.hasOwn(user, "name");          // true
Object.hasOwn(user, "toString");      // false
Object.getOwnPropertyNames(user);     // ["name"]

Q128 of 311 · Objects, this & prototypes

Property descriptors

What are writable, enumerable, configurable?

writable: can assign. enumerable: shows in keys/for...in. configurable: can delete or change the descriptor. defineProperty sets them. class fields and methods have specific defaults worth knowing.

Example

JavaScript
const user = {};
Object.defineProperty(user, "id", {
  value: 1,
  writable: false,
  enumerable: false,
  configurable: false,
});
Object.getOwnPropertyDescriptor(user, "id");
Object.keys(user); // [] — not enumerable

Q129 of 311 · Objects, this & prototypes

Getters and setters

How do get/set work?

get name() runs on read; set name(v) on write. They look like properties. Useful for computed fields. They can hide expensive work — be careful in hot paths. defineProperty can add them too.

Example

JavaScript
const temp = {
  c: 25,
  get f() {
    return this.c * 1.8 + 32;
  },
  set f(value) {
    this.c = (value - 32) / 1.8;
  },
};
temp.f;     // 77
temp.f = 86;
temp.c;     // 30

Q130 of 311 · Objects, this & prototypes

class syntax

What does class actually do?

Syntactic sugar over prototypes plus: constructor, methods on prototype, static on the function, extends/super, and implicit strict mode. Instance fields may live on the instance. new is required.

Example

JavaScript
class User {
  constructor(name) {
    this.name = name;
  }
  hi() {
    return "Hi " + this.name;
  }
  static create(name) {
    return new User(name);
  }
}
User.create("Ada").hi(); // "Hi Ada"

Q131 of 311 · Objects, this & prototypes

extends and super

When must you call super()?

In a subclass constructor, before using this. super.method() calls the parent prototype method. static methods can use super too. extends can use a built-in like Array — there are some exotic built-in caveats.

Example

JavaScript
class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    return this.name;
  }
}
class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }
  speak() {
    return super.speak() + " barks";
  }
}
new Dog("Rex", "Indie").speak(); // "Rex barks"

Q132 of 311 · Objects, this & prototypes

static methods

Where do statics live?

On the constructor function, not instances. Array.isArray is static. Subclasses inherit statics via the constructor’s prototype chain. Call them as Class.method(), not this.method() unless you mean the constructor.

Example

JavaScript
class Mathx {
  static clamp(n, min, max) {
    return Math.min(max, Math.max(min, n));
  }
}
Mathx.clamp(12, 0, 10); // 10
new Mathx(); // instance does not get clamp unless you put it on prototype

Q133 of 311 · Objects, this & prototypes

Private fields

What is #name?

Truly private class fields, not accessible outside the class body. They are not just underscore conventions. Weak-map-like per instance. They make instanceof-style checks with in #field possible.

Example

JavaScript
class Wallet {
  #cents = 0;
  deposit(n) {
    this.#cents += n;
  }
  get rupees() {
    return this.#cents / 100;
  }
}
const w = new Wallet();
w.deposit(250);
w.rupees; // 2.5
// w.#cents; // SyntaxError

Q134 of 311 · Objects, this & prototypes

this in class methods

Why bind class methods?

Passing this.handleClick to addEventListener loses this. Bind in the constructor, use class fields with arrows (handleClick = () => ...), or wrap in an arrow at the call site.

Example

JavaScript
class Button {
  clicks = 0;
  handleClick = () => {
    this.clicks += 1;
  };
  handleClickOld() {
    this.clicks += 1;
  }
}
const b = new Button();
const detached = b.handleClickOld;
// detached(); // TypeError — this lost
b.handleClick(); // field arrow is bound

Q135 of 311 · Objects, this & prototypes

Object.assign vs spread

How do you copy objects?

Object.assign(target, ...sources) mutates target and copies enumerable own properties. { ...obj } is a shallow copy. Nested objects are still shared. Neither copies prototypes or descriptors faithfully.

Examples

JavaScript
const a = { name: "Ada", city: "Pune" };
const b = { city: "Mumbai", age: 30 };
const merged = Object.assign({}, a, b);
// { name: "Ada", city: "Mumbai", age: 30 }

const spread = { ...a, ...b };
a.city; // still "Pune"

Q136 of 311 · Objects, this & prototypes

Shallow vs deep copy

Why does spreading not deep-copy?

Spread copies one level. Nested arrays/objects are the same references. Mutating copy.user.name mutates original.user.name. Use structuredClone or a deep clone for nested data.

Examples

JavaScript
const original = { user: { name: "Ada" } };
const shallow = { ...original };
shallow.user.name = "Bea";
original.user.name; // "Bea" — shared nested object

const deep = structuredClone(original);
deep.user.name = "Cara";
original.user.name; // "Bea"

Q137 of 311 · Objects, this & prototypes

Map vs object

When is Map better than a plain object?

Map keys can be any value (including objects). Size is .size. Insertion order is guaranteed. No prototype key collisions. Objects are better for JSON and record-shaped data with known string keys.

Examples

JavaScript
const scores = new Map();
const user = { id: 1 };
scores.set(user, 10); // object key
scores.get(user); // 10
scores.size; // 1

const rec = { name: "Ada" }; // JSON / known keys
JSON.stringify(rec);

Q138 of 311 · Objects, this & prototypes

Set vs array

When do you use Set?

Unique values, O(1) has, union/intersection helpers in modern JS. Arrays keep duplicates and order of all inserts. Convert with [...set] and new Set(arr).

Examples

JavaScript
const set = new Set([1, 2, 2, 3]);
[...set]; // [1, 2, 3]
set.has(2); // true

const arr = [1, 2, 2, 3];
arr.includes(2); // true — keeps duplicates

Q139 of 311 · Objects, this & prototypes

WeakMap and WeakSet

Why WeakMap?

Keys must be objects; they are weakly held so they can be garbage-collected. Used for private data and caches that should not keep objects alive. Not iterable. WeakSet is a set of objects only.

Examples

JavaScript
const privateData = new WeakMap();
const user = { name: "Ada" };
privateData.set(user, { token: "abc" });
privateData.get(user); // { token: "abc" }
// when `user` is GC'd, the entry can disappear

const seen = new WeakSet();
seen.add(user);
seen.has(user); // true

Q140 of 311 · Objects, this & prototypes

instanceof

How does instanceof work?

It walks the prototype chain looking for Constructor.prototype. Can be spoofed with Symbol.hasInstance. Fails across iframes for some built-ins — prefer Array.isArray. A custom class instance is instanceof that class and Object.

Example

JavaScript
class User {}
const ada = new User();
ada instanceof User;   // true
ada instanceof Object; // true
[] instanceof Array;   // true
Array.isArray([]);     // prefer this for arrays

Q141 of 311 · Objects, this & prototypes

Object.prototype.toString

Why Object.prototype.toString.call(x)?

It returns tags like [object Array], [object Null]. A classic type-check before Array.isArray existed. Still used for distinguishing boxed types and host objects.

Example

JavaScript
Object.prototype.toString.call([]);        // "[object Array]"
Object.prototype.toString.call(null);      // "[object Null]"
Object.prototype.toString.call(new Date()); // "[object Date]"

Q142 of 311 · Objects, this & prototypes

new.target

What is new.target?

In a constructor, new.target is the constructor that was directly invoked with new (the subclass if called via super). It is undefined if the function was called without new. Useful to detect missing new.

Example

JavaScript
function User(name) {
  if (!new.target) {
    return new User(name);
  }
  this.name = name;
}
User("Ada").name;     // "Ada"
new User("Ada").name; // "Ada"

Q221 of 311 · Objects, this & prototypes

Ways to create objects

How can you create an object in JavaScript?

Object literal { a: 1 } is the default. new Constructor() or new class {}. Object.create(proto) sets the prototype without running a constructor. Object.assign / spread copy enumerable own keys. Almost never use new Object() — a literal is clearer. Factories return objects without new.

Example

JavaScript
const literal = { role: "qa" };
const copy = { ...literal, lang: "js" };
const proto = Object.create(null);
proto.role = "qa";
class User {
  constructor(name) {
    this.name = name;
  }
}
const ada = new User("Ada");

Q222 of 311 · Objects, this & prototypes

Dot vs bracket access

How do you read object properties?

Dot (user.name) for known identifiers. Brackets (user[key]) when the key is in a variable or not a valid identifier (user["full-name"]). Optional chaining user?.name. Computed keys in literals: { [key]: value }.

Q223 of 311 · Objects, this & prototypes

Empty object check

How do you test that an object has no own keys?

Object.keys(obj).length === 0 for enumerable string keys. Object.entries is the pairs version. Reflect.ownKeys also sees symbols and non-enumerable keys. JSON.stringify({}) is "{}" but is a poor test (order, undefined keys).

Example

JavaScript
const obj = {};
Object.keys(obj).length === 0; // true
Object.keys({ a: undefined }).length; // 1 — key exists
Object.hasOwn(obj, "toString"); // false
"toString" in obj; // true (prototype)

Q224 of 311 · Objects, this & prototypes

Object.keys, values, entries

What is the difference?

keys: enumerable own string keys. values: the matching values. entries: [key, value] pairs, handy for Object.fromEntries and Map. None of them walk the prototype chain. Order follows the usual integer-index then insertion rules.

Q225 of 311 · Objects, this & prototypes

Object.defineProperty

When do you use defineProperty instead of assignment?

When you need non-enumerable, read-only, or getter/setter fields. Assignment creates a writable enumerable configurable data property. Libraries hide internals this way. class fields have their own defaults — do not mix blindly.

Q293 of 311 · Objects, this & prototypes

Copying properties

How do you copy props from one object to another?

Object.assign(target, source) mutates target. { ...source, ...overrides } builds a new object. Neither clones nested objects. For descriptors, getOwnPropertyDescriptors + defineProperties.

Q294 of 311 · Objects, this & prototypes

Does a key exist?

How do you check a key on an object?

Object.hasOwn(obj, key) for own keys. key in obj includes the prototype (so "toString" in {} is true). obj.key !== undefined misses the key whose value is undefined. Maps use map.has(key).

Q295 of 311 · Objects, this & prototypes

Looping over objects

How do you enumerate keys?

Object.keys + for...of, or Object.entries. for...in includes inherited enumerable keys — filter with hasOwn if you must use it. Avoid for...in on arrays.

Q296 of 311 · Objects, this & prototypes

Add a key at runtime

How do you add a property?

obj[key] = value or obj.key = value. Spread into a new object if you are treating data as immutable. defineProperty if you need attributes. Map.set if keys are not strings.

Arrays & strings

Q168 of 311 · Arrays & strings

map, filter, reduce

When do you use each?

map transforms every item to a new array of the same length. filter keeps items that pass a test. reduce folds to any result (sum, object, array). Prefer map/filter for readability; reduce when you are actually accumulating. Do not mutate in map.

Example

JavaScript
const nums = [1, 2, 3];
nums.map((n) => n * 2);          // [2, 4, 6]
nums.filter((n) => n > 1);       // [2, 3]
nums.reduce((sum, n) => sum + n, 0); // 6

Q169 of 311 · Arrays & strings

find vs filter vs includes vs some

How do you search an array?

includes tests a value with SameValueZero (finds NaN). some tests a predicate (boolean). find returns the first matching element. filter returns all matches. findIndex returns the index or -1. Use the smallest tool that answers the question.

Example

JavaScript
[1, 2, 3].includes(2);                 // true
[1, 2, 3].some((n) => n > 2);          // true
[1, 2, 3].find((n) => n > 2);          // 3
[1, 2, 3].filter((n) => n > 1);        // [2, 3]
[1, 2, 3].findIndex((n) => n === 2);   // 1
[NaN].includes(NaN);                   // true

Q170 of 311 · Arrays & strings

Array.sort

Why does [10, 2, 1].sort() go wrong?

Default sort converts to strings, so "10" < "2". Pass a comparator: (a,b) => a-b for numbers. sort mutates the array — copy first if you need immutability. The comparator should be consistent or you get nonsense order.

Example

JavaScript
[10, 2, 1].sort();                 // [1, 10, 2] — string sort
[10, 2, 1].sort((a, b) => a - b);  // [1, 2, 10]
const copy = [...[10, 2, 1]].sort((a, b) => a - b);

Q171 of 311 · Arrays & strings

slice vs splice

What is the difference?

slice(start, end) copies a range and does not mutate. splice(start, deleteCount, ...items) mutates: removes/inserts and returns removed items. Confusing these two is a rite of passage.

Example

JavaScript
const a = [1, 2, 3, 4];
a.slice(1, 3);        // [2, 3] — copy, a unchanged
a.splice(1, 2, 9);    // removes 2,3 inserts 9 → a is [1, 9, 4]

Q172 of 311 · Arrays & strings

concat vs spread vs push

How do you combine arrays?

a.concat(b) and [...a, ...b] create a new array. push mutates and returns the new length. concat treats array args as values to merge; push of an array inserts the array as one item unless you spread.

Example

JavaScript
const a = [1, 2];
const b = [3];
a.concat(b);     // [1, 2, 3]
[...a, ...b];    // [1, 2, 3]
a.push(b);       // a is [1, 2, [3]] — nested
a.push(...b);    // spread to append items

Q173 of 311 · Arrays & strings

slice, substring, substr

Which string method should you use?

slice supports negative indices and is the one to remember. substring forbids negatives (swaps if start > end). substr is legacy. Prefer slice plus padStart/padEnd, includes, startsWith, endsWith.

Example

JavaScript
"JavaScript".slice(0, 4);      // "Java"
"JavaScript".slice(-6);        // "Script"
"JavaScript".substring(0, 4);  // "Java"
"hello".padStart(8, ".");      // "...hello"

Q174 of 311 · Arrays & strings

replace vs replaceAll

Why does replace only hit once?

With a string pattern, replace changes the first match only. Use a global regex or replaceAll. replace with a function gets (match, groups, offset, string). Remember regex state with /g and lastIndex.

Example

JavaScript
"aaa".replace("a", "b");     // "baa"
"aaa".replaceAll("a", "b");  // "bbb"
"aaa".replace(/a/g, "b");    // "bbb"
"Ada Lovelace".replace(/(\w+) (\w+)/, "$2, $1"); // "Lovelace, Ada"

Q175 of 311 · Arrays & strings

String building

When are template literals better?

Readability, interpolation, and multi-line. For huge loops, push chunks into an array and join. Tagged templates enable DSLs. Avoid HTML injection — templates do not escape.

Examples

JavaScript
const name = "Ada";
"Hi " + name + "!";
`Hi ${name}!`;

const rows = ["Ada", "Bea"].map((n) => `<li>${n}</li>`);
`<ul>${rows.join("")}</ul>`;

Q281 of 311 · Arrays & strings

Regular expressions

How do regexes work in JS?

Literals /pattern/flags or new RegExp(string, flags). Flags: g i m s u y d. test, exec, match, matchAll, search, replace, split. /g plus exec uses lastIndex — a classic loop bug. Prefer String includes when the text is literal.

Q282 of 311 · Arrays & strings

Substring checks

How do you test if a string contains another?

haystack.includes(needle). startsWith / endsWith for edges. indexOf !== -1 is the old form. For patterns, regex.test. All are case-sensitive unless you normalize with toLowerCase or a unicode-aware fold.

Q283 of 311 · Arrays & strings

trim and title case

How do you trim and capitalize?

trim / trimStart / trimEnd drop whitespace. Title case is not built-in: split on spaces, uppercase first code point, join — and still fail on names and unicode. toUpperCase is locale-insensitive; use Intl for real i18n.

Q284 of 311 · Arrays & strings

Multiline strings

How do you write a string on several lines?

Template literals. Or "line\n" + "next". Old escaped newlines with a trailing \ are a museum piece. Prefer templates for SQL/HTML snippets, and still escape untrusted data.

Q285 of 311 · Arrays & strings

reverse and toReversed

How do you reverse an array?

arr.reverse() mutates and returns the same array. Copy first ([...arr].reverse()) or use toReversed() when you want a new array. Strings have no reverse; split/reverse/join is a UTF-16 trap for emoji.

Q286 of 311 · Arrays & strings

Min and max of an array

How do you get the smallest and largest numbers?

Math.min(...nums) / Math.max(...nums) — spread can blow the stack on huge arrays. Reduce: nums.reduce((m, n) => Math.min(m, n), Infinity). Empty arrays need a policy (throw vs undefined).

Q311 of 311 · Arrays & strings

Validate an email

How do you validate an email in JS?

A perfect RFC regex does not exist. Use input type=email for UX, a reasonable pattern for obvious typos, and verify on the server (and with a confirmation mail). Do not copy a 200-character regex from a blog as “complete.”

Callbacks, promises & async

Q143 of 311 · Callbacks, promises & async

What is a callback?

Explain callbacks with an example.

A callback is a function you pass to be called later — when a timer fires, a click happens, or an async result arrives. Array map/filter also take callbacks, but those run now. Async callbacks are the old Node style: fs.readFile(path, (err, data) => ...). The danger is inversion of control: you trust the callee to call you once, correctly.

Examples

JavaScript
function loadUser(id, callback) {
  setTimeout(() => callback(null, { id, name: "Ada" }), 100);
}

loadUser(1, (err, user) => {
  if (err) return console.error(err);
  console.log(user.name);
});

Q144 of 311 · Callbacks, promises & async

Callback hell

What is callback hell and how do you escape it?

Nested callbacks for sequential async work indent into a pyramid, error handling repeats, and variables leak across levels. Escape with named functions, Promises, or async/await. Promises flatten the chain; async/await looks synchronous while still being non-blocking.

Example

JavaScript
// nested callbacks vs async/await
async function load() {
  const user = await fetchUser();
  const posts = await fetchPosts(user.id);
  return posts;
}

Q145 of 311 · Callbacks, promises & async

Error-first callbacks

What is the Node (err, data) convention?

The first argument is an Error or null, the rest are success values. You must check err before using data. Forgetting that check is a common bug. Promises replace this with .then/.catch or try/catch around await.

Examples

JavaScript
function readName(ok, callback) {
  setTimeout(() => {
    if (!ok) return callback(new Error("fail"));
    callback(null, "Ada");
  }, 20);
}

readName(true, (err, name) => {
  if (err) return console.error(err);
  console.log(name); // "Ada"
});

Q146 of 311 · Callbacks, promises & async

What is a Promise?

Define a Promise and its states.

A Promise is an object for a future value. States: pending, fulfilled, rejected. It settles once. .then(onSuccess, onFail), .catch, .finally. Creating: new Promise((resolve, reject) => ...). Wrapping callbacks: new Promise((resolve, reject) => fs.readFile(p, (e, d) => e ? reject(e) : resolve(d))).

Example

JavaScript
const p = new Promise((resolve, reject) => {
  setTimeout(() => resolve("done"), 50);
});
p.then(console.log);

Q147 of 311 · Callbacks, promises & async

How does then chaining work?

What does a then callback return?

If you return a value, the next then receives it. If you return a Promise, the chain waits. If you throw, the chain rejects. Returning nothing passes undefined. Always return/throw from then to keep the chain honest. Flattening nested thens is the point of chaining.

Examples

JavaScript
Promise.resolve(2)
  .then((n) => n * 2)
  .then((n) => Promise.resolve(n + 1))
  .then((n) => console.log(n)); // 5

Promise.resolve(1)
  .then(() => {
    throw new Error("boom");
  })
  .then(() => console.log("skip"))
  .catch((err) => console.log(err.message)); // "boom"

Q148 of 311 · Callbacks, promises & async

catch vs then’s second argument

Where should you put error handlers?

.catch(fn) is .then(undefined, fn). A rejection skips to the next catch. If onSuccess throws, a second-arg rejection handler on the same then does not see it — a following catch does. Prefer one catch at the end unless you recover in the middle.

Examples

JavaScript
Promise.reject("nope")
  .then(
    () => "ok",
    (err) => "recovered:" + err,
  )
  .then(console.log); // recovered:nope

Promise.resolve()
  .then(() => {
    throw new Error("from success handler");
  })
  .then(null, () => "this second arg misses the throw above")
  .catch((err) => err.message); // "from success handler"

Q149 of 311 · Callbacks, promises & async

Promise.finally

What does finally do?

Runs after settle, success or fail, for cleanup (spinners, locks). It does not receive the value. If it throws, that rejection wins. If it returns a thenable, the chain waits. The previous fulfillment value still flows through unless finally fails.

Examples

JavaScript
let loading = true;
Promise.resolve("data")
  .finally(() => {
    loading = false;
  })
  .then(console.log); // "data" still flows through

Promise.reject("x")
  .finally(() => console.log("cleanup"))
  .catch((err) => err);

Q150 of 311 · Callbacks, promises & async

Promise.all

When do you use Promise.all?

Run independent async work in parallel and wait for all. Resolves with an array in input order. Rejects on the first rejection (fail fast). Empty array resolves immediately to []. Use allSettled if you need every outcome.

Example

JavaScript
const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);

Q151 of 311 · Callbacks, promises & async

Promise.allSettled

How is allSettled different from all?

It waits for every promise and never short-circuits. Each result is { status: "fulfilled", value } or { status: "rejected", reason }. Perfect for reporting which of many uploads failed.

Example

JavaScript
const results = await Promise.allSettled([
  Promise.resolve("ok"),
  Promise.reject("fail"),
]);
// [
//   { status: "fulfilled", value: "ok" },
//   { status: "rejected", reason: "fail" }
// ]

Q152 of 311 · Callbacks, promises & async

Promise.race

What does race do?

Settles with the first promise that settles, success or failure. Used for timeouts: race(fetch(url), delay(3000).then(() => Promise.reject("timeout"))). The slower promise still runs unless you abort it.

Examples

JavaScript
function timeout(ms) {
  return new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), ms));
}

const winner = await Promise.race([
  fetch("/api"),
  timeout(3000),
]);

Q153 of 311 · Callbacks, promises & async

Promise.any

What does Promise.any do?

Fulfills with the first fulfillment. Rejects only if every input rejects, with an AggregateError. Useful when any mirror/CDN succeeding is enough.

Examples

JavaScript
const firstOk = await Promise.any([
  Promise.reject("down"),
  Promise.resolve("cdn-2"),
  Promise.resolve("cdn-3"),
]);
// "cdn-2"

// Promise.any([Promise.reject(1), Promise.reject(2)])
// rejects with AggregateError

Q154 of 311 · Callbacks, promises & async

async/await

How does async/await relate to Promises?

async functions always return a Promise. await pauses that function (not the whole thread) until the thenable settles, then returns the value or throws. try/catch works. Sequential awaits wait one after another; wrap independent ones in Promise.all.

Example

JavaScript
async function main() {
  try {
    const data = await fetch("/api").then((r) => r.json());
    return data;
  } catch (err) {
    console.error(err);
  }
}

Q155 of 311 · Callbacks, promises & async

await in a loop

Is awaiting inside for...of bad?

It is correct when each step depends on the previous. It is slow when requests are independent — then map to promises and Promise.all. forEach(async () => await ...) does not wait for the inner promises; interviewers love that trap.

Examples

JavaScript
const ids = [1, 2, 3];

// sequential — each waits
for (const id of ids) {
  await fetch("/users/" + id);
}

// parallel — independent
await Promise.all(ids.map((id) => fetch("/users/" + id)));

// trap: forEach does not wait
ids.forEach(async (id) => {
  await fetch("/users/" + id);
});

Q156 of 311 · Callbacks, promises & async

Unhandled promise rejections

What happens if you forget catch?

The rejection is unhandled. Browsers log it; Node may warn or crash depending on version/flags. Always catch or return the promise to a caller who will. void p.catch(console.error) is a last resort at boundaries.

Examples

JavaScript
Promise.reject("oops"); // unhandled — always catch at a boundary

async function load() {
  try {
    return await fetch("/api");
  } catch (err) {
    console.error(err);
    return null;
  }
}

Q157 of 311 · Callbacks, promises & async

Promisify a callback API

How do you wrap an error-first callback in a Promise?

new Promise((resolve, reject) => api(arg, (err, data) => err ? reject(err) : resolve(data))). Node has util.promisify. Do not resolve and reject — only one settle.

Examples

JavaScript
function readFileFake(path, callback) {
  callback(null, "contents of " + path);
}

function readFile(path) {
  return new Promise((resolve, reject) => {
    readFileFake(path, (err, data) => (err ? reject(err) : resolve(data)));
  });
}

await readFile("notes.txt");

Q268 of 311 · Callbacks, promises & async

Server-sent events

What are server-sent events?

EventSource: a one-way HTTP stream of text events from the server. Auto-reconnects. Simpler than WebSocket when you only need server → client. POST and binary need WebSocket or fetch streams.

Q269 of 311 · Callbacks, promises & async

Does Promise.all cancel the rest?

If one promise rejects, do the others stop?

No. Promise.all rejects early but the other tasks still run unless you abort them (AbortController). Same for race. Always plan cancellation for fetches.

Example

JavaScript
const ac = new AbortController();
const p = fetch("/slow", { signal: ac.signal });
Promise.all([p, Promise.reject(new Error("fail"))]).catch(() => {
  ac.abort(); // without this, /slow still runs
});

Q270 of 311 · Callbacks, promises & async

Promise rules

What are the main Promise rules?

A promise settles once (fulfilled or rejected). then returns a new promise. Throwing in then rejects. Returning a thenable assimilates it. The executor runs sync. Non-function then handlers are ignored.

Q271 of 311 · Callbacks, promises & async

XHR vs fetch

How do you make an HTTP request?

fetch returns a Promise, does not reject on HTTP 404 (check response.ok), needs AbortController to cancel, and has no progress events. XMLHttpRequest is event-based and can track upload progress. Prefer fetch plus async/await in new code.

Q272 of 311 · Callbacks, promises & async

Synchronous HTTP

Should you make a sync XHR?

No. xhr.open(method, url, false) blocks the thread and is being removed. Use async fetch. The question exists so you say you would never ship it.

Q303 of 311 · Callbacks, promises & async

Why callbacks exist

Why do we need callbacks?

JS is single-threaded. You cannot block waiting for a click or HTTP. You register a function to run later. Promises/async are better syntax for the same idea when the “later” is a single result.

Q304 of 311 · Callbacks, promises & async

Why Promises?

Why were Promises added?

Composable then/catch, one settle, easier errors than pyramids, and a standard thenable that async/await sits on. They do not make CPU parallel. They do not cancel unless you add AbortController.

Event loop & browser

Q158 of 311 · Event loop & browser

Microtasks vs macrotasks

What runs first: Promise.then or setTimeout(0)?

After the current call stack, the engine drains the microtask queue (Promise then/catch, queueMicrotask, MutationObserver) before the next macrotask (setTimeout, setInterval, I/O, UI events). So Promise.resolve().then(fn) runs before setTimeout(fn, 0).

Example

JavaScript
setTimeout(() => console.log("timeout"), 0);
Promise.resolve().then(() => console.log("microtask"));
console.log("sync");
// sync, microtask, timeout

Q159 of 311 · Event loop & browser

The event loop

Explain the JS event loop.

JS is single-threaded with a call stack. Async work is scheduled as tasks. The event loop takes a macrotask, runs it, then runs all microtasks, then may render, then the next macrotask. That is why long CPU work freezes UI — it never yields. Web Workers / Worker threads move CPU off the main thread.

Example

JavaScript
console.log("1 sync");
setTimeout(() => console.log("4 timeout"), 0);
Promise.resolve().then(() => console.log("3 microtask"));
console.log("2 sync");
// 1 2 3 4

Q160 of 311 · Event loop & browser

Rendering and the event loop

When does the browser paint?

Typically after microtasks of a task, before the next task, aligned with the frame. Endless microtasks (a then that always queues another then) can starve rendering. requestAnimationFrame runs before the next paint.

Examples

JavaScript
function starve() {
  Promise.resolve().then(starve); // endless microtasks — UI can freeze
}
// starve();

requestAnimationFrame(() => {
  // runs before the next paint — good for visual updates
});

Q161 of 311 · Event loop & browser

setInterval pitfalls

Why is setInterval unreliable?

If the callback takes longer than the interval, calls can stack or skip depending on the environment. Busy pages delay timers. Recursive setTimeout(fn, delay) at the end of fn is often easier to control. Clear intervals on unmount.

Examples

JavaScript
let id = setInterval(() => console.log("tick"), 1000);
clearInterval(id);

function tick() {
  console.log("tick");
  setTimeout(tick, 1000); // wait until work finishes, then schedule
}

Q162 of 311 · Event loop & browser

requestAnimationFrame

When do you use rAF instead of setTimeout?

For visual work tied to refresh rate (~60Hz). The callback gets a timestamp. Pause when the tab is hidden. Better than setTimeout(16) for animations.

Example

JavaScript
function animate(ts) {
  // use ts for a smooth time delta
  box.style.transform = "translateX(" + ((ts / 10) % 200) + "px)";
  requestAnimationFrame(animate);
}
const handle = requestAnimationFrame(animate);
cancelAnimationFrame(handle);

Q163 of 311 · Event loop & browser

What blocks the event loop?

What blocks the event loop?

Synchronous CPU: huge loops, JSON.parse of megabytes, complex regex on untrusted strings (ReDoS). Alert() blocks. Network does not block the thread if you use async APIs. Split work with chunks + setTimeout/rAF or workers.

Examples

JavaScript
console.log("start");
const t = Date.now();
while (Date.now() - t < 2000) {} // blocks clicks and paint for 2s
console.log("end");

function chunked(items, fn) {
  const item = items.shift();
  if (!item) return;
  fn(item);
  setTimeout(() => chunked(items, fn), 0);
}

Q164 of 311 · Event loop & browser

fetch

How does fetch work? Does it reject on 404?

fetch returns a Promise of a Response. Network failure rejects. HTTP 404/500 still fulfill — check response.ok or status. Then response.json()/text() is another Promise. Use AbortController to cancel.

Example

JavaScript
const res = await fetch("/api/users");
if (!res.ok) throw new Error(res.status);
const data = await res.json();

Q165 of 311 · Event loop & browser

AbortController

How do you cancel fetch?

const c = new AbortController(); fetch(url, { signal: c.signal }); c.abort(). The fetch promise rejects with AbortError. Pass the same signal to timeouts if you want both to cancel. Essential for React effects cleanup.

Example

JavaScript
const controller = new AbortController();
const p = fetch("/slow", { signal: controller.signal });
controller.abort();
p.catch((err) => console.log(err.name)); // AbortError

Q166 of 311 · Event loop & browser

CORS

Why does the browser block a fetch to another origin?

Same-origin policy. Cross-origin requests need CORS headers from the server (Access-Control-Allow-Origin, etc.). Simple vs preflight (OPTIONS) requests. CORS is a browser rule — Postman is not a browser. Credentials need extra headers and cannot use *.

Examples

JavaScript
// Browser: fetch("https://api.other.com/data")
// blocked unless that server sends:
// Access-Control-Allow-Origin: https://your-site.com
// (or * for public, no cookies)

fetch("https://api.other.com/data", {
  credentials: "include",
}); // needs Allow-Credentials + a specific origin, not *

Q167 of 311 · Event loop & browser

Sending JSON with fetch

What headers do you set for POST JSON?

method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(obj). Forgetting stringify or the header is a classic bug. Do not JSON.stringify FormData.

Example

JavaScript
await fetch("/api/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Ada" }),
});

Q247 of 311 · Event loop & browser

encodeURI vs encodeURIComponent

How do you encode a URL?

encodeURI keeps the URL shape (does not encode : / ? &). encodeURIComponent encodes a single query value or path segment so & cannot split the query. Pair with decodeURI / decodeURIComponent. Never use escape/unescape.

Example

JavaScript
encodeURI("https://ex.com/a b"); // keeps : / 
encodeURIComponent("a&b=c"); // "a%26b%3Dc"
const params = new URLSearchParams({ q: "a&b" });
params.toString(); // "q=a%26b"

Q248 of 311 · Event loop & browser

location

How do you read the current URL?

location.href is the whole URL. Also host, hostname, pathname, search, hash, origin. location.assign / replace navigate (replace skips history). new URL(location.href).searchParams is the modern query API.

Q249 of 311 · Event loop & browser

Query strings

How do you read ?id=1&q=hi?

new URLSearchParams(location.search).get("id"). getAll for repeated keys. toString to serialize. Manual split/decode is error-prone. URLSearchParams is also usable in Node.

Example

JavaScript
const params = new URLSearchParams("?id=1&tag=a&tag=b");
params.get("id"); // "1"
params.getAll("tag"); // ["a", "b"]
params.set("id", "2");

Q250 of 311 · Event loop & browser

Redirect in JavaScript

How do you send the user to another page?

location.assign(url) or location.href = url adds history. location.replace(url) does not. For SPAs, use the router instead of a full load. window.open for a new tab (often blocked without a click).

Q251 of 311 · Event loop & browser

History API

How do you access history?

history.back(), forward(), go(n). history.pushState(state, "", url) and replaceState change the URL without reload; popstate fires on back/forward, not on pushState. Routers are built on this.

Q252 of 311 · Event loop & browser

window vs document

What is the difference?

window is the global browser object (BOM): location, history, fetch, timers. document is the DOM tree for this tab. document.defaultView is the window. Node has neither unless you polyfill.

Q253 of 311 · Event loop & browser

BOM

What is the Browser Object Model?

The browser host APIs around the page: window, navigator, location, history, screen, frames. Not part of ECMAScript. navigator.userAgent is a weak signal; prefer feature detection.

Q264 of 311 · Event loop & browser

postMessage

What is window.postMessage?

Cross-origin (or worker) messaging: otherWindow.postMessage(data, targetOrigin). Always check event.origin on the receiver. Structured clone, not a live reference. iframes, popups, and service workers use this.

Q265 of 311 · Event loop & browser

Web workers

What is a web worker?

A background thread for JS. No DOM access. Talk via postMessage. Good for heavy CPU so the UI stays responsive. Dedicated workers vs shared vs service workers are different tools. Feature-detect Worker.

Examples

JavaScript
// worker.js
self.onmessage = (event) => {
  self.postMessage(event.data * 2);
};

const worker = new Worker("worker.js");
worker.onmessage = (event) => console.log(event.data);
worker.postMessage(21); // 42

Q266 of 311 · Event loop & browser

Service worker

What is a service worker?

A worker that sits on the network path: intercept fetch, cache, offline, push. HTTPS (or localhost). No DOM. Lifecycle: install, activate, fetch. Hard to debug — unregister while developing. PWAs are built on this plus a manifest.

Q267 of 311 · Event loop & browser

PWA

What is a Progressive Web App?

A site that can install, work offline, and feel app-like: HTTPS, web app manifest, service worker. Not a separate language. “App shell” means cache the chrome, then fill content.

Q273 of 311 · Event loop & browser

Same-origin policy

What is the same-origin policy?

A origin is scheme + host + port. JS on https://a.com cannot read https://b.com’s DOM or cookies. CORS is the server opt-in for fetch/XHR. iframes can still display other origins; postMessage is the safe talk channel.

Q274 of 311 · Event loop & browser

clearTimeout and clearInterval

How do you cancel a timer?

const id = setTimeout(fn, ms); clearTimeout(id). Same with setInterval / clearInterval. Clearing an already-fired timeout is a no-op. Store the id if the component can unmount.

Q275 of 311 · Event loop & browser

setInterval

What is the pitfall of setInterval?

It schedules on a fixed cadence even if fn is still running — work can overlap. Prefer recursive setTimeout after the work finishes, or a loop with await delay. Drift and background-tab clamping apply to both.

Q309 of 311 · Event loop & browser

Window size

How do you measure the viewport?

window.innerWidth / innerHeight include the scrollbar area in most browsers. document.documentElement.clientWidth is the layout viewport without scrollbars. Use matchMedia for breakpoints instead of resize-throttled pixel checks when you can.

ES6+ & patterns

Q176 of 311 · ES6+ & patterns

ES6 features to name

List ES6 features interviewers expect.

let/const, arrows, classes, template literals, destructuring, default/rest/spread, for...of, Map/Set, Promise, modules, Symbol, generators, computed property names. Then ES2017 async/await, ES2020 optional chaining and ??. Knowing the year is optional; knowing the behavior is not.

Example

JavaScript
const add = (a, b) => a + b;
const [first, ...rest] = [1, 2, 3];
const user = { name: "Ada", age: 30 };
const { name, ...meta } = user;
Promise.resolve(1).then((n) => n + 1);
const city = user.address?.city ?? "Pune";

Q177 of 311 · ES6+ & patterns

Computed property names

What is { [key]: value }?

The key expression is evaluated. Useful for dynamic fields and Symbol keys. Shorthand { name } is name: name. Combining shorthand and computed keys is everyday React state code.

Example

JavaScript
const field = "score";
const user = {
  name: "Ada",
  [field]: 10,
  [Symbol("id")]: 1,
};
user.score; // 10

Q178 of 311 · ES6+ & patterns

Method shorthand

What is { greet() {} } vs greet: function(){}

Shorthand methods are still callable with this from the call site. Do not use arrow methods on object literals if you need this to be the object when called as obj.greet() — actually obj.greet as arrow would capture outer this. Interviewers check that you know arrows on objects are wrong for methods.

Example

JavaScript
const name = "Ada";
const user = {
  name,
  hi() {
    return this.name;
  },
  // bad as a method if you need this:
  // hi: () => this.name,
};
user.hi(); // "Ada"

Q179 of 311 · ES6+ & patterns

Why static import?

Why static import?

Static import/export lets bundlers tree-shake unused exports and load dependencies ahead of time. Dynamic import() returns a Promise and is for code-splitting. Circular imports behave differently than CJS — design modules to avoid cycles.

Examples

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

// app.js — bundler can drop unused()
import { add } from "./math.js";

const page = await import("./heavy-chart.js"); // code-split

Q180 of 311 · ES6+ & patterns

Default vs named exports

Which should you use?

Named exports rename safely and tree-shake well. Default exports are convenient but harder to grep and to re-export consistently. Many style guides prefer named-only. You can mix both; importers must match.

Examples

JavaScript
// named (prefer)
export function add(a, b) { return a + b; }
import { add } from "./math.js";

// default
export default function area(w, h) { return w * h; }
import area from "./math.js";

Q181 of 311 · ES6+ & patterns

Modern syntax odds and ends

What are ?. ?? ??= numeric separators?

Optional chaining, nullish coalescing, logical assignment (x ??= 1), 1_000_000 separators, BigInt, Promise.allSettled, globalThis, Array.at(-1), Object.hasOwn. Listing a few current ones shows you still read release notes.

Examples

JavaScript
try {
  JSON.parse("{");
} catch {
  console.log("bad json");
}

let volume = 0;
volume ||= 5;  // 5 — 0 is falsy
volume = 0;
volume ??= 5;  // 0

[1, 2, 3].at(-1); // 3

Q182 of 311 · ES6+ & patterns

Module pattern

What is the module pattern?

An IIFE that returns a public API and hides private vars via closure. ES modules replaced it for files, but the idea (exports vs private) is the same. Revealing module pattern names the internals then returns a subset.

Example

JavaScript
const cart = (() => {
  const items = [];
  return {
    add(item) {
      items.push(item);
    },
    list() {
      return [...items];
    },
  };
})();
cart.add("book");
cart.list(); // ["book"]

Q183 of 311 · ES6+ & patterns

Observer / pub-sub

How would you implement events?

An object with on/off/emit storing arrays of listeners per event name. DOM EventTarget is the platform version. Unsubscribe is mandatory to avoid leaks. Promises are one-shot; events are many-shot.

Example

JavaScript
function createBus() {
  const listeners = new Map();
  return {
    on(event, fn) {
      if (!listeners.has(event)) listeners.set(event, []);
      listeners.get(event).push(fn);
    },
    emit(event, data) {
      (listeners.get(event) ?? []).forEach((fn) => fn(data));
    },
  };
}
const bus = createBus();
bus.on("login", (u) => console.log(u));
bus.emit("login", "Ada");

Q184 of 311 · ES6+ & patterns

Singleton in JS

How do you make one instance?

A module that exports a single object is already a singleton (ESM is evaluated once). class with a static instance is the OOP version. In tests, singletons are painful to reset — prefer injecting dependencies.

Examples

JavaScript
// config.js — ESM is already a singleton
export const config = { api: "/v1" };

// class version
class DB {
  static #instance;
  static get() {
    return (this.#instance ??= new DB());
  }
}
DB.get() === DB.get(); // true

Q185 of 311 · ES6+ & patterns

Factory functions

Why factories instead of new?

A function that returns an object (often with closures for privacy). No this confusion, easy composition. class is better when you need instanceof and a prototype of methods shared on memory. Both are valid JS style.

Example

JavaScript
function createUser(name) {
  let score = 0;
  return {
    name,
    add(n) {
      score += n;
    },
    getScore() {
      return score;
    },
  };
}
const ada = createUser("Ada");
ada.add(5);
ada.getScore(); // 5

Q226 of 311 · ES6+ & patterns

Proxy

What is a Proxy?

new Proxy(target, handler) intercepts get, set, apply, construct, and more. Used for logging, validation, reactive UIs, and virtual APIs. Traps must respect invariants or you throw. Debugging proxies is harder than a plain object — use them with a reason.

Example

JavaScript
const user = { name: "Ada" };
const logged = new Proxy(user, {
  get(target, key, receiver) {
    console.log("get", key);
    return Reflect.get(target, key, receiver);
  },
});
logged.name; // logs get name → "Ada"

Q227 of 311 · ES6+ & patterns

Reflect

What is Reflect for?

A namespace of functions that mirror Proxy traps: Reflect.get, set, apply, construct. Default trap implementations often call Reflect.* so you forward correctly. Prefer Reflect.deleteProperty over the delete operator when you care about the boolean result.

Q279 of 311 · ES6+ & patterns

Polyfill

What is a polyfill?

Code that implements a modern API on older engines (Array.prototype.flat, Promise). Feature-detect first. core-js and browser targets in your bundler ship them. A polyfill is not a transpiler — Babel rewrites syntax; polyfills add functions.

Q280 of 311 · ES6+ & patterns

Tree shaking

What is tree shaking?

Bundlers drop unused ESM exports when the graph is static (no mystery side effects). Prefer named exports and avoid import * as if you only need one function. Side-effectful modules must be marked or they cannot be shaken.

Q290 of 311 · ES6+ & patterns

What is Node.js?

How is Node different from the browser?

A JS runtime (V8) plus libuv for I/O. No DOM. Has fs, process, Buffer, CommonJS/ESM. The event loop still applies. Testers meet it as Playwright/Cypress runners and as the place API helpers run.

Q291 of 311 · ES6+ & patterns

Decorators

What are decorators?

A proposed / stage syntax (@logged class, @bound method) wrapping classes and members. TypeScript has used them for years. Native JS decorators are still catching up — say you know they are wrappers, and check the compiler settings.

Q302 of 311 · ES6+ & patterns

Why modules?

Why not put everything in one file?

Namespacing, reuse, lazy load, tree-shaking, and a clear public API. Without modules you get globals and copy-paste. ESM is the language’s module system; bundlers still emit files the browser can cache.

DOM & storage

Q186 of 311 · DOM & storage

Selecting elements

querySelector vs getElementById vs getElementsBy*

getElementById is fastest for one id. querySelector/querySelectorAll take CSS selectors; All returns a static NodeList. getElementsByClassName returns a live HTMLCollection that updates as the DOM changes — a classic footgun.

Examples

JavaScript
document.getElementById("app");
document.querySelector(".item.active");
document.querySelectorAll("li"); // static NodeList

const live = document.getElementsByClassName("item");
// live updates if you add another .item

Q187 of 311 · DOM & storage

Creating DOM nodes

innerHTML vs createElement vs insertAdjacentHTML

createElement + textContent is safest against XSS. innerHTML parses HTML and can run scripts in some cases / is the XSS vector. insertAdjacentHTML is like innerHTML at a position. DocumentFragment batches inserts.

Examples

JavaScript
const li = document.createElement("li");
li.textContent = userInput; // safe

// li.innerHTML = userInput; // XSS if userInput is markup

const frag = document.createDocumentFragment();
frag.append(li);
list.append(frag);

Q188 of 311 · DOM & storage

textContent vs innerText vs innerHTML

Which do you use?

textContent is the raw text tree, fast, no styles. innerText is CSS-aware and slower (reflow). innerHTML is markup. Never assign untrusted strings to innerHTML.

Example

JavaScript
el.textContent = "<b>Ada</b>"; // shows the tags as text
el.innerHTML = "<b>Ada</b>";   // bold Ada — unsafe with user data
el.innerText;                  // visible text, slower

Q189 of 311 · DOM & storage

Bubbling vs capturing

How do events travel?

Capturing phase root → target, then bubbling target → root. addEventListener(type, fn, true) listens in capture. Most handlers use bubble (default). stopPropagation stops the walk; stopImmediatePropagation also skips other listeners on the same node.

Example

JavaScript
parent.addEventListener("click", () => console.log("bubble"));
parent.addEventListener("click", () => console.log("capture"), true);
child.addEventListener("click", (e) => {
  console.log("target");
  e.stopPropagation();
});

Q190 of 311 · DOM & storage

Event delegation

Why listen on a parent?

One listener on a stable parent handles many children, including those added later. Use event.target / closest(selector). Required for large lists. Check the target is still inside the parent.

Example

JavaScript
list.addEventListener("click", (event) => {
  const btn = event.target.closest("button.delete");
  if (!btn || !list.contains(btn)) return;
  btn.closest("li")?.remove();
});

Q191 of 311 · DOM & storage

preventDefault

When do you need it?

Stops the browser’s default (form submit navigation, link navigate, context menu). It does not stop bubbling — that is stopPropagation. return false in onclick does both in old jQuery; in addEventListener it does not.

Examples

JavaScript
form.addEventListener("submit", (event) => {
  event.preventDefault();
  console.log("send via fetch instead");
});

link.addEventListener("click", (event) => {
  event.preventDefault();
  event.stopPropagation();
});

Q192 of 311 · DOM & storage

event.target vs currentTarget

What is the difference?

target is the innermost element that was clicked. currentTarget is the element whose listener is running (the delegated parent). Use currentTarget for this-like behavior with arrows.

Example

JavaScript
parent.addEventListener("click", (event) => {
  console.log(event.target);        // the inner button you clicked
  console.log(event.currentTarget); // parent — the listener's element
});

Q193 of 311 · DOM & storage

localStorage vs sessionStorage vs cookies

Compare web storage.

localStorage: origin, persists, ~5MB, strings only, sync, readable by JS (XSS can steal it). sessionStorage: per tab. cookies: sent to the server, smaller, HttpOnly can hide from JS. Do not store access tokens in localStorage if you can use HttpOnly cookies.

Examples

JavaScript
localStorage.setItem("theme", "dark");
localStorage.getItem("theme"); // "dark"
sessionStorage.setItem("draft", "hello"); // gone when tab closes

// cookies: document.cookie — sent to the server; HttpOnly cookies are hidden from JS

Q194 of 311 · DOM & storage

Storing objects in localStorage

How do you save an object?

JSON.stringify on write, JSON.parse on read, try/catch parse errors. QuotaExceededError if too large. Storage events fire in other tabs, not the one that wrote.

Examples

JavaScript
localStorage.setItem("user", JSON.stringify({ name: "Ada" }));
const user = JSON.parse(localStorage.getItem("user") || "null");

try {
  JSON.parse(localStorage.getItem("broken"));
} catch {
  localStorage.removeItem("broken");
}

Q195 of 311 · DOM & storage

data-* attributes

How do you read data-user-id?

element.dataset.userId (camelCase). Good for small flags. Not for large JSON. Prefer one listener + data on the row for tables.

Example

JavaScript
el.dataset.userId = "42";
el.getAttribute("data-user-id"); // "42"
el.dataset.userId;               // "42"

Q196 of 311 · DOM & storage

Reflow vs repaint

What layout thrashing?

Reflow (layout) recalculates geometry; repaint fills pixels. Reading offsetHeight after writes forces layout. Batch DOM writes, use fragments, class toggles, and measure once. This is a senior-level performance question.

Examples

JavaScript
// thrash: write, read, write, read...
el.style.width = "100px";
const w = el.offsetWidth;
el.style.width = "200px";
const w2 = el.offsetWidth;

// batch writes, then read once
el.style.width = "200px";
el.style.height = "40px";
const box = el.getBoundingClientRect();

Q254 of 311 · DOM & storage

DOMContentLoaded vs load

When does each fire?

DOMContentLoaded: HTML parsed, DOM ready, stylesheets may still load (defer scripts have run). load: everything including images and stylesheets. Put DOM queries in DOMContentLoaded or at the end of body. load is late for UI setup.

Q255 of 311 · DOM & storage

What are events?

Explain the event model.

Signals that something happened: click, input, submit, fetch completion. You listen with addEventListener. The browser dispatches an Event / CustomEvent. Handlers should be short; heavy work belongs after, in a worker, or async.

Q256 of 311 · DOM & storage

stopPropagation

What does stopPropagation do?

Stops the event from reaching other nodes in capture/bubble. It does not cancel the default action — that is preventDefault. stopImmediatePropagation also skips remaining listeners on the same node. Overuse makes debugging painful.

Q257 of 311 · DOM & storage

return false in handlers

What does return false do?

In an HTML onclick attribute or jQuery, it often preventDefault + stopPropagation. In addEventListener, returning false does nothing useful. Always call preventDefault explicitly.

Q258 of 311 · DOM & storage

Submit a form from JS

How do you submit a form in JavaScript?

form.requestSubmit() runs constraint validation and fires submit. form.submit() sends without the submit event (skips listeners). Prevent the default on submit, then fetch if you are not doing a full navigation.

Q259 of 311 · DOM & storage

Attribute vs property

What is the difference on a DOM node?

Attributes are the HTML string (getAttribute). Properties are the live JS fields (el.value, el.checked). The value attribute is the initial value; the value property is what the user typed. Keep them straight in tests.

Q260 of 311 · DOM & storage

Changing styles

How do you style an element from JS?

el.classList.add/remove/toggle is the maintainable way. el.style.color sets an inline style. cssText overwrites the inline style string. Prefer CSS classes over a pile of inline styles.

Q262 of 311 · DOM & storage

storage event

When does the storage event fire?

On other documents of the same origin when localStorage (or sessionStorage in some cases) changes — not in the tab that wrote. Use it to sync logout across tabs. The event has key, oldValue, newValue, url.

Q263 of 311 · DOM & storage

IndexedDB

What is IndexedDB?

A browser database for structured data, indexes, and larger payloads than localStorage. Async, transactional, same-origin. Awkward raw API; libraries wrap it. Use it for offline apps, not for a few flags — those belong in memory or localStorage.

Q308 of 311 · DOM & storage

Image width and height

How do you read an image’s size?

img.naturalWidth / naturalHeight after load (intrinsic). img.width / height are layout sizes. Listen for load; a broken src gives 0. For files, URL.createObjectURL plus an Image().

Tricky interview favorites

Q197 of 311 · Tricky interview favorites

[] == ![]

What is [] == ![] ?

true, because ![] is false, [] == false becomes [] == 0 becomes "" == 0 becomes 0 == 0. These puzzles test coercion, not good code. Say you never write that, then walk ToPrimitive.

Examples

JavaScript
[] == ![]; // true
// ![] → false
// [] == false → [] == 0 → "" == 0 → 0 == 0

[] === ![]; // false — never write this

Q198 of 311 · Tricky interview favorites

typeof NaN

What is typeof NaN?

"number". NaN is a numeric value meaning invalid. Number.isNaN is the check. This pair with 0.1+0.2 is the numeric trivia set.

Example

JavaScript
typeof NaN;            // "number"
Number.isNaN(NaN);     // true
Number("x");           // NaN

Q199 of 311 · Tricky interview favorites

[] + {} and {} + []

Why are they different?

[] + {} is string concat: "" + "[object Object]". {} + [] at the start of a statement can be interpreted as a block plus an array (unary +[] → 0) depending on ASI/context. Another reason to use explicit conversion.

Example

JavaScript
[] + {}; // "[object Object]"
// +[] → 0 when {} is parsed as a block in some statement positions
String([]); // ""
String({}); // "[object Object]"

Q200 of 311 · Tricky interview favorites

var fn = function vs function fn

What prints if both share a name?

Function declarations hoist fully. var fn = function(){} hoists fn as undefined then assigns. Duplicate declarations interact in sloppy function scope. Prefer const and one style to avoid the puzzle.

Examples

JavaScript
console.log(typeof fn); // "function" if declared as function fn(){}
function fn() {}

var gn = function () {};
console.log(typeof gn); // "function" only after this line

Q201 of 311 · Tricky interview favorites

setTimeout inside for

How do you print 0,1,2 with timeouts?

let i in the loop, or bind i, or IIFE, or setTimeout(..., 0, i) passing the extra arg. var will print 3,3,3. Pair this with closures.

Examples

JavaScript
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i), 0);
// 3 3 3

for (let i = 0; i < 3; i++) setTimeout(() => console.log(i), 0);
// 0 1 2

Q202 of 311 · Tricky interview favorites

Log order: sync, promise, timeout

Predict console order.

Synchronous first, then microtasks (promises), then timers. If a then queues another then, those still run before the timeout. Draw the queues on the whiteboard.

Example

JavaScript
console.log("A");
setTimeout(() => console.log("D"), 0);
Promise.resolve().then(() => console.log("C"));
console.log("B");
// A B C D

Q203 of 311 · Tricky interview favorites

this inside setTimeout

Why is this wrong in a method’s timeout?

setTimeout(this.fn, 0) detaches the method. setTimeout(() => this.fn(), 0) keeps lexical this in an arrow. bind also works. Same issue as passing React handlers.

Example

JavaScript
const counter = {
  n: 0,
  startBroken() {
    setTimeout(this.tick, 0); // tick loses this
  },
  start() {
    setTimeout(() => this.tick(), 0);
  },
  tick() {
    this.n += 1;
  },
};

Q204 of 311 · Tricky interview favorites

const object mutation

Can you change a const object?

Yes. const prevents reassignment of the binding, not mutation of the value. Freeze if you need immutability. This is the #1 const misconception.

Examples

JavaScript
const user = { name: "Ada" };
user.name = "Bea"; // ok
// user = {};      // TypeError

const nums = [1];
nums.push(2); // ok

Q205 of 311 · Tricky interview favorites

delete arr[0]

What does delete do on arrays?

It removes the index and leaves a hole; length may stay. Use splice to compact. Sparse arrays skip holes in map depending on empty slots vs undefined. Prefer splice/filter.

Examples

JavaScript
const a = [1, 2, 3];
delete a[1];
a;          // [1, empty, 3]
a.length;   // 3
a.map((n) => n); // skips the hole

const b = [1, 2, 3];
b.splice(1, 1); // [1, 3]

Q206 of 311 · Tricky interview favorites

arguments in arrows

Can arrows use arguments?

No own arguments; they close over the outer function’s arguments if any. Use rest. Mixing arguments and arrows is a gotcha when refactoring a function to an arrow.

Examples

JavaScript
function outer() {
  const inner = () => arguments[0];
  return inner();
}
outer("Ada"); // "Ada" — inherited arguments

const broken = () => arguments[0];
// broken("x"); // ReferenceError in most modules

Q207 of 311 · Tricky interview favorites

return on a new line

What does return\n{ a: 1 } return?

undefined. ASI inserts after return. Wrap the object in parentheses: return { a: 1 }. A legendary bug.

Examples

JavaScript
function bad() {
  return
  { ok: true }
}
bad(); // undefined

function good() {
  return { ok: true };
}
good(); // { ok: true }

Q208 of 311 · Tricky interview favorites

['1','2','3'].map(parseInt)

What happens?

map passes (value, index, array). parseInt('1', 0), parseInt('2', 1), parseInt('3', 2) → 1, NaN, NaN. Use map(Number) or map((s) => parseInt(s, 10)).

Examples

JavaScript
["1", "2", "3"].map(parseInt);
// parseInt("1", 0) → 1
// parseInt("2", 1) → NaN
// parseInt("3", 2) → NaN

["1", "2", "3"].map((s) => parseInt(s, 10)); // [1, 2, 3]
["1", "2", "3"].map(Number); // [1, 2, 3]

Q209 of 311 · Tricky interview favorites

Object.is vs ===

When do they differ?

Object.is(NaN, NaN) is true, === is false. Object.is(0, -0) is false, === is true. Everything else matches. Object.is is SameValue.

Example

JavaScript
NaN === NaN;           // false
Object.is(NaN, NaN);   // true
0 === -0;              // true
Object.is(0, -0);      // false

Q210 of 311 · Tricky interview favorites

Executor runs when?

When does new Promise(fn) call fn?

Immediately, synchronously, on construction. The async work inside should use resolve later. Heavy CPU in the executor still blocks. People think the executor waits — it does not.

Example

JavaScript
console.log("A");
new Promise((resolve) => {
  console.log("B"); // runs now
  resolve("C");
}).then(console.log);
console.log("D");
// A B D C

Q211 of 311 · Tricky interview favorites

then(null) / then(1)

What if you pass a non-function to then?

It is ignored (identity). p.then(1).then(fn) still gets the previous fulfillment. The spec calls this "thenable assimilation" details — enough to say non-callables are skipped.

Example

JavaScript
Promise.resolve(1)
  .then(1)
  .then((n) => n + 1)
  .then(console.log); // 2 — non-function then is skipped

Q212 of 311 · Tricky interview favorites

throw vs reject in async

Is throw new Error the same as return Promise.reject?

In an async function, yes — both reject the returned promise. Outside, throw is sync and will crash if uncaught; Promise.reject is async unhandled if nobody catches. Mixing styles in one function is messy.

Example

JavaScript
async function a() {
  throw new Error("nope");
}
async function b() {
  return Promise.reject(new Error("nope"));
}
// both reject the returned promise
a().catch((e) => e.message);

Q213 of 311 · Tricky interview favorites

await 1

Does await always defer?

await on a thenable always continues as a microtask, even await 1. So after await, you are not still in the same synchronous turn. That surprises people who await a non-promise.

Example

JavaScript
async function demo() {
  console.log("1");
  await 1; // still defers as a microtask
  console.log("3");
}
demo();
console.log("2");
// 1 2 3

Q214 of 311 · Tricky interview favorites

typeof undeclared vs TDZ

typeof x when x is undeclared vs let x in TDZ?

typeof undeclaredVar is "undefined". typeof x when let x is in TDZ throws ReferenceError. A sharp distinction.

Examples

JavaScript
typeof missing; // "undefined"

{
  // typeof boxed; // ReferenceError
  let boxed = 1;
  typeof boxed; // "number"
}

Q215 of 311 · Tricky interview favorites

with statement

Why is with forbidden in strict mode?

It puts an object at the front of the scope chain, making name lookup ambiguous and killing optimizations. Do not use it. Mention it only to say it is banned.

Examples

JavaScript
// forbidden in strict mode / modules
const user = { name: "Ada" };
// with (user) { console.log(name); } // do not use

const { name } = user;
console.log(name); // do this instead

Q216 of 311 · Tricky interview favorites

eval

Why avoid eval?

Runs a string as code: XSS, no bundler help, slow (deopts). Indirect eval vs direct eval have different scopes. JSON.parse is for data. new Function is similarly dangerous.

Examples

JavaScript
const data = '{"n":1}';
JSON.parse(data); // do this for data

// eval("user." + field); // XSS / injection — never
const user = { name: "Ada" };
user[field]; // safe property access

Q217 of 311 · Tricky interview favorites

Common JS memory leaks

Name a few.

Detached DOM nodes still referenced, forgotten event listeners / intervals, closures holding large data, global caches, Map keys that never get deleted (use WeakMap when keys are objects). DevTools heap snapshots find them.

Examples

JavaScript
const leaking = [];
function onClick() {
  leaking.push(document.body.innerHTML);
}
button.addEventListener("click", onClick);
// later:
button.removeEventListener("click", onClick);

const cache = new WeakMap(); // lets unused object keys be GC'd

Q218 of 311 · Tricky interview favorites

XSS in the browser

How does innerHTML relate to XSS?

Injecting unsanitized HTML/JS from users runs in their origin. Use textContent, sanitizer APIs, CSP, and never eval user input. localStorage tokens are stealable if XSS exists. This is a must for frontend interviews.

Examples

JavaScript
el.textContent = userName; // safe
// el.innerHTML = userName; // XSS if userName is <img onerror=...>

const html = document.createElement("div");
html.textContent = comment;
list.append(html);

Q219 of 311 · Tricky interview favorites

Debounce vs throttle (when)

When would you pick each?

Debounce: wait until the user paused (search box). Throttle: cap rate while the event keeps firing (scroll position). They are not interchangeable. Implement both at least once before the interview.

Examples

JavaScript
const search = debounce((q) => fetch("/search?q=" + q), 300);
input.addEventListener("input", (e) => search(e.target.value));

const onScroll = throttle(() => {
  console.log(window.scrollY);
}, 100);
window.addEventListener("scroll", onScroll);

Q220 of 311 · Tricky interview favorites

offsetWidth after write

What is layout thrashing?

A loop that writes style then reads offsetHeight each time forces layout every iteration. Batch writes, then read once. requestAnimationFrame can help schedule visual work.

Examples

JavaScript
const els = document.querySelectorAll(".box");
for (const el of els) {
  el.style.height = "40px";
  el.offsetHeight; // forces layout every time — thrash
}

for (const el of els) el.style.height = "40px";
els[0]?.offsetHeight; // measure once after writes

Q241 of 311 · Tricky interview favorites

1 + 2 + '3'

What is 1 + 2 + "3" vs "3" + 1 + 2?

Left to right: 1+2 is 3, 3+"3" is "33". "3"+1 is "31", then "31"+2 is "312". + is the only arithmetic operator that prefers strings. Spell out Number or String when the types mixed.

Example

JavaScript
1 + 2 + "3"; // "33"
"3" + 1 + 2; // "312"
String(1 + 2) + "3"; // "33"
Number("3") + 1 + 2; // 6

238 / 311 · Number.isFinite

Teams and tool vendors can sponsor this page.