---
title: "JavaScript Intermediate Flashcards"
description: "Intermediate and advanced JavaScript concepts for deeper mastery using spaced repetition."
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/flashcards/post/javascript-intermediate-flashcards
---

# JavaScript Intermediate Flashcards

## Flashcards

### 1. What is a Promise in JavaScript?

A Promise is an object representing the eventual completion or failure of an asynchronous operation. It can be in one of three states pending, fulfilled, or rejected and allows chaining with .then() and .catch().

```
const p = new Promise((resolve, reject) => {
  setTimeout(() => resolve("done"), 1000);
});
p.then(val => console.log(val)); // "done"

```

### 2. What is async/await?

async/await is syntactic sugar over Promises. An async function always returns a Promise, and the await keyword pauses execution inside that function until the awaited Promise settles.

```
async function fetchData() {
  const res = await fetch("https://api.example.com/data");
  const json = await res.json();
  return json;
}

```

### 3. What is the difference between == and ===?

== performs loose equality with type coercion, meaning values of different types may be considered equal. === performs strict equality with no type coercion both value and type must match.

```
console.log(0 == "0");  // true  (coercion)
console.log(0 === "0"); // false (strict)

```

### 4. What is the prototype chain?

Every JavaScript object has an internal link to another object called its prototype. When a property is not found on an object, the engine walks up the prototype chain until it finds it or reaches null.

```
function Animal(name) { this.name = name; }
Animal.prototype.speak = function() {
  console.log(this.name + " makes a noise.");
};
const a = new Animal("Dog");
a.speak(); // "Dog makes a noise."

```

### 5. What is the difference between call, apply, and bind?

All three set the value of 'this'. call() invokes the function immediately with arguments listed individually. apply() invokes it immediately with arguments as an array. bind() returns a new function with 'this' bound, without calling it.

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

```

### 6. What are higher-order functions?

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

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

```

### 7. What is destructuring assignment?

Destructuring is a syntax that allows unpacking values from arrays or properties from objects into distinct variables in a single statement.

```
const [a, b] = [10, 20];
const { name, age } = { name: "Ali", age: 30 };
console.log(a, b);       // 10 20
console.log(name, age);  // Ali 30

```

### 8. What is the spread operator?

The spread operator (...) expands an iterable (like an array or object) into individual elements. It is commonly used for copying, merging, or passing arguments.

```
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 }; // { a: 1, b: 2 }

```

### 9. What is the rest parameter?

The rest parameter (...) collects all remaining function arguments into a real array. Unlike the arguments object, rest parameters are actual arrays and can use array methods directly.

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

```

### 10. What is a generator function?

A generator function (function*) returns a Generator object. It can pause execution and resume later using the yield keyword, making it useful for lazy iteration and async flows.

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

```

### 11. What is a Symbol in JavaScript?

Symbol is a primitive data type introduced in ES6. Every Symbol value is unique and immutable, and is often used as unique property keys to avoid name collisions in objects.

```
const id = Symbol("id");
const user = { [id]: 123, name: "Alice" };
console.log(user[id]); // 123

```

### 12. What is the nullish coalescing operator (??)?

The ?? operator returns the right-hand operand when the left-hand operand is null or undefined. Unlike ||, it does not treat 0, false, or empty string as falsy.

```
const val = null ?? "default"; // "default"
const zero = 0 ?? "default";   // 0

```

### 13. What is optional chaining (?.)?

Optional chaining (?.) allows reading deeply nested properties without throwing an error if an intermediate value is null or undefined. It short-circuits and returns undefined instead.

```
const user = { address: { city: "Amman" } };
console.log(user?.address?.city);  // "Amman"
console.log(user?.phone?.number);  // undefined

```

### 14. What is a WeakMap?

A WeakMap is a collection of key-value pairs where keys must be objects and are held weakly. If no other references to the key exist, it can be garbage-collected, making WeakMap useful for private data and caching.

```
const wm = new WeakMap();
let obj = {};
wm.set(obj, "secret");
console.log(wm.get(obj)); // "secret"

```

### 15. What is a WeakSet?

A WeakSet is a collection of objects only (no primitives), held weakly. If no other references to an object in the set exist, it may be garbage-collected. Useful for tracking objects without preventing GC.

### 16. What is the difference between map() and forEach()?

map() transforms each element and returns a new array. forEach() iterates over elements for side effects and always returns undefined. Use map() when you need a transformed result.

```
const a = [1, 2, 3].map(n => n * 2);    // [2, 4, 6]
[1, 2, 3].forEach(n => console.log(n));  // undefined returned

```

### 17. What is Promise.all()?

Promise.all() takes an iterable of Promises and returns a single Promise that resolves when all input Promises resolve, or rejects immediately if any one of them rejects.

```
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
Promise.all([p1, p2]).then(values => {
  console.log(values); // [1, 2]
});

```

### 18. What is Promise.allSettled()?

Promise.allSettled() waits for all Promises to settle (either resolve or reject) and returns an array of objects describing each outcome, never short-circuiting on rejection.

### 19. What is a Proxy in JavaScript?

A Proxy wraps an object and intercepts fundamental operations on it (get, set, delete, etc.) via handler traps. It enables powerful patterns like validation, logging, and reactive data.

```
const handler = {
  get(target, key) {
    return key in target ? target[key] : "N/A";
  }
};
const p = new Proxy({ name: "Ali" }, handler);
console.log(p.name);  // "Ali"
console.log(p.age);   // "N/A"

```

### 20. What is Reflect in JavaScript?

Reflect is a built-in object that provides static methods mirroring those interceptable by Proxy traps (e.g., Reflect.get, Reflect.set). It makes it easier to forward operations inside Proxy handlers.

### 21. What is tail call optimization?

Tail call optimization (TCO) allows a function call in tail position (the last action of a function) to reuse the current stack frame instead of creating a new one, preventing stack overflow in deep recursion. ES6 specifies TCO but most engines only partially support it.

### 22. What is debouncing?

Debouncing delays executing a function until after a specified wait time has passed since the last time it was called. Useful for limiting expensive operations triggered by rapid events like keystrokes or window resizing.

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

```

### 23. What is throttling?

Throttling ensures a function is called at most once in a specified time interval, regardless of how many times the trigger fires. Unlike debouncing, it guarantees regular execution during continuous events.

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

```

### 24. What is memoization?

Memoization is an optimization technique that caches the results of expensive function calls and returns the cached result when the same inputs occur again. It trades memory for speed.

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

```

### 25. What is currying?

Currying transforms a function that takes multiple arguments into a sequence of functions, each taking a single argument. It enables partial application and more reusable function composition.

```
const add = a => b => a + b;
const add5 = add(5);
console.log(add5(3)); // 8

```

### 26. What is the module pattern?

The module pattern uses an IIFE to create a private scope, exposing only selected properties and methods via a returned object. It was the standard way to encapsulate code before ES modules.

```
const counter = (() => {
  let count = 0;
  return {
    increment: () => ++count,
    getCount: () => count,
  };
})();
counter.increment();
console.log(counter.getCount()); // 1

```

### 27. What is an IIFE?

An IIFE (Immediately Invoked Function Expression) is a function that is defined and called immediately. It creates its own scope to avoid polluting the global namespace.

```
(function() {
  const x = 10;
  console.log(x); // 10
})();
// x is not accessible outside

```

### 28. What is the difference between deep copy and shallow copy?

A shallow copy duplicates only the top-level properties; nested objects are still referenced. A deep copy recursively duplicates all levels so there are no shared references between the original and the copy.

```
const obj = { a: 1, b: { c: 2 } };
// Shallow copy
const shallow = { ...obj };
shallow.b.c = 99; // also mutates obj.b.c

// Deep copy
const deep = JSON.parse(JSON.stringify(obj));

```

### 29. What is event bubbling and capturing?

Event bubbling means an event propagates from the target element up through its ancestors. Event capturing (trickling) is the opposite the event travels from the root down to the target. addEventListener's third argument controls which phase to listen on.

```
// true = capturing phase, false (default) = bubbling phase
element.addEventListener("click", handler, true);

```

### 30. What are iterators and iterables?

An iterable is an object that implements the [Symbol.iterator] method returning an iterator. An iterator is an object with a next() method that returns { value, done }. Arrays, strings, Maps, and Sets are built-in iterables.

```
const range = {
  [Symbol.iterator]() {
    let n = 1;
    return { next: () => n <= 3 ? { value: n++, done: false } : { done: true } };
  }
};
for (const x of range) console.log(x); // 1 2 3

```

### 31. What is the difference between null and undefined?

undefined means a variable has been declared but not yet assigned a value. null is an intentional assignment representing the absence of a value. typeof undefined is "undefined"; typeof null is "object" (a known language quirk).

### 32. What is short-circuit evaluation?

Short-circuit evaluation means logical operators (&&, ||) stop evaluating as soon as the result is determined. && returns the first falsy value or the last value; || returns the first truthy value or the last value.

```
console.log(false && doSomething()); // false, doSomething never called
console.log(true  || doSomething()); // true,  doSomething never called

```

### 33. What is a tagged template literal?

A tagged template literal applies a tag function to a template string. The tag receives the string parts as an array and the interpolated values as separate arguments, enabling custom string processing.

```
function highlight(strings, ...vals) {
  return strings.reduce((acc, str, i) =>
    acc + str + (vals[i] ? `<b>${vals[i]}</b>` : ""), "");
}
const name = "Alice";
console.log(highlight`Hello ${name}!`); // Hello <b>Alice</b>!

```

### 34. What is the arguments object?

The arguments object is an array-like object available inside non-arrow functions containing all passed arguments. Unlike rest parameters, it is not a real array and lacks array methods. Arrow functions do not have their own arguments object.

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

```
