Free Resource

JavaScript Interview
Cheat Sheet 2025

A complete quick-reference for every JavaScript concept you need to know before your frontend interview. Printable, bookmarkable, shareable.

Or practice these concepts interactively →
ClosuresEvent LoopPromises & async/awaitthis KeywordPrototypal Inheritancevar / let / constArray MethodsHoistingDestructuring & SpreadDebounce vs Throttle

Closures

  • A closure is a function that retains access to its outer scope after the outer function returns.
  • Created every time a function is created, at function creation time.
  • Key use cases: data encapsulation, factory functions, memoization, event handlers with state.
  • Classic gotcha: var in for-loops shares the binding. Fix with let or IIFE.
function counter() {
  let n = 0;
  return {
    inc: () => ++n,
    val: () => n,
  };
}
const c = counter();
c.inc(); c.inc();
c.val(); // 2

Event Loop

  • JavaScript is single-threaded with a non-blocking event loop.
  • Call stack → Microtasks (all) → Next macrotask → Microtasks → ...
  • Microtasks: Promise callbacks, queueMicrotask, MutationObserver.
  • Macrotasks: setTimeout, setInterval, I/O, UI rendering.
console.log('1');
setTimeout(() => console.log('2'), 0); // macro
Promise.resolve().then(() => console.log('3')); // micro
console.log('4');
// Output: 1 → 4 → 3 → 2

Promises & async/await

  • Promise states: pending → fulfilled / rejected. Immutable once settled.
  • Combinators: Promise.all (all resolve), .race (first settles), .allSettled (all done), .any (first resolves).
  • async function always returns a Promise. await pauses execution of that function only.
  • Always handle rejections — unhandled rejections crash Node.js.
// Sequential (slow)
const a = await fetchA();
const b = await fetchB();

// Parallel (fast ~2x)
const [a, b] = await Promise.all([
  fetchA(),
  fetchB(),
]);

this Keyword

  • this is determined by HOW a function is called, not where defined.
  • Global: window (browser) or undefined (strict mode).
  • Method call: the object before the dot.
  • new: the new object. call/apply/bind: explicit. Arrow: lexical outer scope.
const obj = {
  val: 42,
  regular() { return this.val; },
  arrow: () => this.val, // undefined
};
const fn = obj.regular;
fn();         // undefined (lost context)
fn.call(obj); // 42

Prototypal Inheritance

  • Every object has [[Prototype]]. Lookup walks chain until null.
  • Object.create(proto) — creates object with proto as prototype.
  • class syntax is syntactic sugar over prototypes.
  • Use hasOwnProperty() to check own vs inherited properties.
const animal = {
  speak() { return '...'; }
};
const dog = Object.create(animal);
dog.name = 'Rex';
dog.speak(); // walks chain → '...'

var / let / const

  • var: function-scoped, hoisted (initialized as undefined), redeclarable.
  • let: block-scoped, hoisted but in Temporal Dead Zone, not redeclarable.
  • const: block-scoped, binding is immutable (value can still mutate if object).
  • Default to const. Use let only when reassignment is needed. Avoid var.
var x = 1; // function scope, leaks
let y = 2; // block scope
const z = []; // binding locked
z.push(1); // ✅ value mutable
z = []; // ❌ TypeError

Array Methods

  • map — transform each element, returns new array of same length.
  • filter — keep matching elements, returns smaller array.
  • reduce — accumulate into any value.
  • find / findIndex — first match. flat / flatMap — flatten. every / some — boolean tests.
const nums = [1,2,3,4,5];
nums.map(n => n * 2);      // [2,4,6,8,10]
nums.filter(n => n > 2);   // [3,4,5]
nums.reduce((s,n) => s+n, 0); // 15
nums.find(n => n > 3);     // 4

Hoisting

  • function declarations: fully hoisted (callable before declaration).
  • var declarations: hoisted, initialized as undefined.
  • let/const: hoisted but in Temporal Dead Zone until declaration line.
  • function expressions and arrow functions: NOT hoisted (follow var/let/const rules).
greet(); // ✅ works
function greet() { ... }

sayHi(); // ❌ TypeError
var sayHi = () => {};

log(x); // ❌ ReferenceError (TDZ)
let x = 5;

Destructuring & Spread

  • Array destructuring: const [a, b] = [1, 2];
  • Object destructuring: const { name, age = 0 } = person;
  • Rest: const { x, ...rest } = obj; — collects remaining props.
  • Spread: merging objects, cloning arrays, passing args.
// Rename + default
const { name: n, age = 18 } = user;

// Swap variables
let a = 1, b = 2;
[a, b] = [b, a];

// Merge objects
const merged = { ...defaults, ...overrides };

Debounce vs Throttle

  • Debounce: fires AFTER the user stops triggering. Best for: search, resize, form validation.
  • Throttle: fires at most once per interval. Best for: scroll, mousemove.
  • Mnemonic: Debounce = waits for storm to pass. Throttle = steady drip.
function debounce(fn, delay) {
  let t;
  return (...a) => {
    clearTimeout(t);
    t = setTimeout(() => fn(...a), delay);
  };
}
const onSearch = debounce(fetch, 300);

What's Not Covered Here

This cheat sheet covers the concepts most frequently tested in interviews. For deeper practice, check:

Ready to Test Yourself?

This cheat sheet gives you the concepts. JSPrep Pro makes you practice them actively — with output prediction, AI-evaluated answers, and mock interviews.

Start Practicing Free →