JavaScript Cheatsheet
Functions
Use this JavaScript reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Function Declaration vs Expression vs Arrow
// Function declaration — hoisted, has its own `this`, `arguments` function add(a, b) { return a + b; } // Function expression — not hoisted const add = function(a, b) { return a + b; }; // Named function expression — name available inside itself only const factorial = function fact(n) { return n <= 1 ? 1 : n * fact(n - 1); }; // Arrow function (ES6) — NOT hoisted, no own `this`, no `arguments`, no `new` const add = (a, b) => a + b; // implicit return const square = x => x * x; // single param, no parens needed const greet = () => "hello"; // no params const getObj = () => ({ key: 1 }); // return object literal — wrap in parens // Arrow with block body const add = (a, b) => { const sum = a + b; return sum; };
Parameters
Defaults (ES6)
function greet(name = "World") { return `Hello, ${name}!`; } greet() // "Hello, World!" greet("Alice") // "Hello, Alice!" // Defaults can reference previous params or call functions function createId(prefix = "id", n = Date.now()) { return `${prefix}_${n}`; } // undefined triggers default; null does NOT greet(undefined) // "Hello, World!" greet(null) // "Hello, null!"
Rest Parameters (ES6)
function sum(...nums) { return nums.reduce((a, b) => a + b, 0); } sum(1, 2, 3, 4) // 10 // Rest must be last function log(level, ...messages) { console.log(`[${level}]`, ...messages); } // vs the legacy `arguments` object (not in arrow functions) function legacy() { console.log(arguments); // array-like object, not a real array const arr = Array.from(arguments); }
Destructuring Parameters
// Object destructuring with defaults function display({ name = "Unknown", age = 0 } = {}) { return `${name}, ${age}`; } display({ name: "Alice", age: 30 }); display(); // uses default empty object // Array destructuring function first([a, b]) { return a; }
Return Values
function nothing() {} // returns undefined function explicit() { return; } // returns undefined function value() { return 42; } // returns 42 // Multiple return values via destructuring function minMax(arr) { return [Math.min(...arr), Math.max(...arr)]; } const [min, max] = minMax([3, 1, 4, 1, 5]); // Return early (guard clause) function divide(a, b) { if (b === 0) return null; return a / b; }
Closures
// A closure captures variables from its outer scope function makeCounter(start = 0) { let count = start; return { increment() { return ++count; }, decrement() { return --count; }, value() { return count; }, }; } const counter = makeCounter(); counter.increment(); // 1 counter.increment(); // 2 counter.value(); // 2 // Classic closure pitfall with var in loops for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); // prints 3 3 3 (all same i) } // Fix with let (block scope) or IIFE for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); // 0 1 2 } // IIFE pattern (Immediately Invoked Function Expression) (function () { let private = 42; })(); // private is not accessible here const result = (() => 42)();
Higher-Order Functions
// Functions as arguments function apply(fn, value) { return fn(value); } apply(Math.sqrt, 16); // 4 // Functions as return values function multiplier(factor) { return x => x * factor; } const double = multiplier(2); const triple = multiplier(3); double(5); // 10 triple(5); // 15 // Common higher-order patterns [1, 2, 3].map(x => x * 2); // [2, 4, 6] [1, 2, 3].filter(x => x > 1); // [2, 3] [1, 2, 3].reduce((a, b) => a + b, 0); // 6
this Binding
// Regular function — `this` depends on call site function show() { console.log(this); } show(); // global (or undefined in strict mode) obj.show(); // obj show.call(ctx); // ctx show.apply(ctx, []); // ctx const bound = show.bind(ctx); bound(); // ctx // Arrow function — `this` is lexically inherited from enclosing scope const obj = { name: "Alice", greet: function() { const inner = () => console.log(this.name); // this = obj inner(); }, }; // Method shorthand (not an arrow — has own this) const obj2 = { name: "Bob", greet() { console.log(this.name); }, // this = obj2 };
call, apply, bind
function greet(greeting, punct) { return `${greeting}, ${this.name}${punct}`; } const user = { name: "Alice" }; greet.call(user, "Hello", "!"); // "Hello, Alice!" greet.apply(user, ["Hello", "!"]); // "Hello, Alice!" (args as array) const bound = greet.bind(user, "Hi"); // returns new function bound("."); // "Hi, Alice." // Partial application with bind function multiply(a, b) { return a * b; } const double = multiply.bind(null, 2); double(5); // 10
Generator Functions (ES6)
function* range(start, end, step = 1) { for (let i = start; i < end; i += step) { yield i; } } for (const n of range(0, 5)) { console.log(n); // 0 1 2 3 4 } [...range(0, 5)] // [0, 1, 2, 3, 4] Array.from(range(0, 5)) // [0, 1, 2, 3, 4] // Manual iteration const gen = range(0, 3); gen.next(); // { value: 0, done: false } gen.next(); // { value: 1, done: false } gen.next(); // { value: 2, done: false } gen.next(); // { value: undefined, done: true } // yield* delegates to another iterable function* concat(...iterables) { for (const it of iterables) yield* it; } // Two-way communication via next(value) function* adder() { let total = 0; while (true) { const n = yield total; total += n ?? 0; } }
Async Functions (ES2017)
async function fetchUser(id) { const res = await fetch(`/api/users/${id}`); if (!res.ok) throw new Error("Not found"); return res.json(); } // Arrow async const fetchUser = async (id) => { const data = await fetch(`/api/users/${id}`).then(r => r.json()); return data; }; // Always returns a Promise fetchUser(1).then(console.log).catch(console.error);
(See the Async cheatsheet for full coverage.)
Function Composition and Currying
// Composition const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x); const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x); const double = x => x * 2; const addOne = x => x + 1; const transform = pipe(double, addOne); transform(3); // 7 // Currying const curry = fn => { const arity = fn.length; return function curried(...args) { if (args.length >= arity) return fn(...args); return (...more) => curried(...args, ...more); }; }; const add = curry((a, b, c) => a + b + c); add(1)(2)(3); // 6 add(1, 2)(3); // 6 add(1)(2, 3); // 6 // Manual curry const add = a => b => a + b; const add5 = add(5); add5(3); // 8
Memoization
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.apply(this, args); cache.set(key, result); return result; }; } const fib = memoize(function(n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); });
Useful Patterns
// IIFE const result = (function() { return 42; })(); const result2 = (() => 42)(); // Function with options object function request(url, { method = "GET", headers = {}, body } = {}) { return fetch(url, { method, headers, body }); } // Throttle function throttle(fn, ms) { let last = 0; return function(...args) { const now = Date.now(); if (now - last >= ms) { last = now; return fn.apply(this, args); } }; } // Debounce function debounce(fn, ms) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), ms); }; } // Once function once(fn) { let called = false, result; return function(...args) { if (!called) { called = true; result = fn.apply(this, args); } return result; }; }