cheat sheet

JavaScript Cheat Sheet

Every method, pattern, and ES6+ feature. Searchable, filterable by level, copy-ready.

/ to focus
level:
JS Snippet Explainer paste any JS expression
Snippet
Breakdown

Variables & Data Types

Quick reference
Declare constant
const name = 'value'
Declare variable
let count = 0
Check type
typeof value
Type conversion
Number('42')

Declarations

beginner
var, let, const - choosing the right declaration
const pi = 3.14; // block-scoped, never reassigned let count = 0; // block-scoped, can be reassigned var legacy = 'avoid'; // function-scoped, hoisted
Primitive data types
const str = 'hello'; // string const num = 42; // number const big = 9007199254740991n;// bigint const bool = true; // boolean const undef = undefined; // undefined const empty = null; // null const sym = Symbol('id'); // symbol
typeof and null gotcha
typeof 'hello' // → 'string' typeof 42 // → 'number' typeof true // → 'boolean' typeof undefined // → 'undefined' typeof null // → 'object' ← historical bug typeof {} // → 'object' typeof [] // → 'object' (use Array.isArray)
Type conversion
Number('42') // → 42 Number('') // → 0 Number(null) // → 0 Number(undefined)// → NaN String(123) // → '123' Boolean(0) // → false (falsy) Boolean('') // → false (falsy) Boolean([]) // → true (truthy!)

Operators & Equality

beginner
== vs === (always use ===)
1 == '1' // → true (coerces types) 1 === '1' // → false (strict, no coercion) null == undefined // → true null === undefined // → false NaN === NaN // → false (use Number.isNaN)
Always use === unless you explicitly need type coercion
Nullish coalescing & optional chaining
const val = user?.name ?? 'Guest'; // ?. → short-circuits if null/undefined // ?? → fallback only for null/undefined (not 0, '') user?.address?.city // deep optional chain arr?.[0] // optional index access fn?.() // optional call
Logical assignment operators
a ||= 'default'; // assign if a is falsy a &&= transform(a); // assign if a is truthy a ??= 'fallback'; // assign if a is null/undefined

Functions

Quick reference
Arrow function
const fn = (x) => x * 2
Default param
function greet(name = 'World') {}
Destructure params
const { a, b } = obj
Explicit this
fn.call(ctx, arg1, arg2)

Function Types

beginner
Function declaration vs expression
// Declaration - hoisted, callable before definition function add(a, b) { return a + b; } // Expression - not hoisted const add = function(a, b) { return a + b; }; // Arrow - no own 'this', implicit return const add = (a, b) => a + b;
Default parameters & rest params
function greet(name = 'World') { return `Hello, ${name}!`; } function sum(...nums) { // rest collects args return nums.reduce((a, b) => a + b, 0); }
IIFE - immediately invoked function
(function() { // runs immediately, own scope const private = 'hidden'; })(); // Arrow IIFE (() => { const local = 42; })();
call, apply, bind
function greet(greeting, punct) { return `${greeting}, ${this.name}${punct}`; } const user = { name: 'Alice' }; greet.call(user, 'Hi', '!'); // spread args greet.apply(user, ['Hi', '!']); // array args const bound = greet.bind(user, 'Hey'); // new fn, fixed this

Closures & Scope

intermediate
Closure - function retaining outer scope
function makeCounter() { let count = 0; return { inc: () => ++count, get: () => count, }; } const c = makeCounter(); c.inc(); c.inc(); c.get(); // → 2
Memoization with closure
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; }; }

Arrays

Quick reference
Transform items
arr.map(x => x * 2)
Filter items
arr.filter(x => x > 0)
Reduce to value
arr.reduce((acc, x) => acc + x, 0)
Merge arrays
[...arr1, ...arr2]

Core Methods

beginner
Add / remove elements
arr.push(item) // add to end → new length arr.pop() // remove from end → removed item arr.unshift(item) // add to start → new length arr.shift() // remove from start → removed item arr.splice(2, 1) // remove 1 item at index 2
map, filter, reduce
const doubled = arr.map(x => x * 2); const evens = arr.filter(x => x % 2 === 0); const sum = arr.reduce((acc, x) => acc + x, 0); // Chain them const result = arr .filter(x => x > 0) .map(x => x * 2) .reduce((a, b) => a + b, 0);
Searching arrays
arr.find(x => x > 3) // first match or undefined arr.findIndex(x => x > 3) // index or -1 arr.includes(5) // true/false arr.indexOf(5) // index or -1 arr.some(x => x > 3) // any match? arr.every(x => x > 0) // all match?
flat, flatMap, from
[1, [2, [3]]].flat() // → [1, 2, [3]] [1, [2, [3]]].flat(Infinity) // → [1, 2, 3] arr.flatMap(x => [x, x * 2]) // map + flatten 1 level Array.from({ length: 3 }, (_, i) => i) // → [0, 1, 2]

Sorting & Transforming

intermediate
Sorting (always provide comparator)
// Numbers arr.sort((a, b) => a - b); // ascending arr.sort((a, b) => b - a); // descending // Strings arr.sort((a, b) => a.localeCompare(b)); // Objects by property arr.sort((a, b) => a.age - b.age);
sort() mutates the original array - use [...arr].sort() for immutable sort
Remove duplicates
// Primitives const unique = [...new Set(arr)]; // Objects by property const unique = arr.filter((v, i, a) => a.findIndex(t => t.id === v.id) === i );
Group array items (Object.groupBy)
// ES2024 const grouped = Object.groupBy( people, person => person.department ); // → { Engineering: [...], Design: [...] }

Objects

Quick reference
Destructure
const { a, b } = obj
Merge objects
{ ...obj1, ...obj2 }
Get keys
Object.keys(obj)
Get entries
Object.entries(obj)

Creating & Accessing

beginner
Object literal & shorthand
const name = 'Alice', age = 30; const user = { name, // shorthand property age, greet() { // shorthand method return `Hi, I'm ${this.name}`; }, ['key_' + age]: true // computed key };
Destructuring with defaults & rename
const { name, age = 25, city: location } = user; // ^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^ // key default rename to 'location' // Nested const { address: { city, zip } } = user; // In function params function show({ name, age = 0 }) { /*...*/ }
Object static methods
Object.keys(obj) // → ['a', 'b', ...] Object.values(obj) // → [1, 2, ...] Object.entries(obj) // → [['a',1], ...] Object.assign({}, obj) // shallow copy Object.freeze(obj) // immutable (shallow) Object.fromEntries(pairs) // pairs → object
Deep clone (structured clone)
// Modern - handles Date, Map, Set, etc. const deep = structuredClone(obj); // JSON trick - only plain data, loses functions/undefined const copy = JSON.parse(JSON.stringify(obj));

Map & Set

intermediate
Map - key-value store with any key type
const map = new Map(); map.set('key', 42); map.get('key'); // → 42 map.has('key'); // → true map.delete('key'); map.size; // → 0 // Iteration for (const [k, v] of map) { /*...*/ }
Set - unique value collection
const set = new Set([1, 2, 2, 3]); set.size; // → 3 set.add(4); set.has(2); // → true set.delete(2); // Set operations const union = new Set([...a, ...b]); const inter = new Set([...a].filter(x => b.has(x)));

Strings

Quick reference
Template literal
`Hello, ${name}!`
Split & trim
str.split(',').map(s => s.trim())
Regex replace
str.replace(/pat/g, 'rep')
Pad string
str.padStart(10, '0')

String Methods

beginner
Searching & checking
str.includes('text') // true/false str.startsWith('http') // true/false str.endsWith('.js') // true/false str.indexOf('sub') // index or -1 str.search(/regex/) // index or -1 str.match(/(\d+)/g) // array or null
Transforming strings
str.toUpperCase() str.toLowerCase() str.trim() // remove both ends str.trimStart() // remove leading str.trimEnd() // remove trailing str.replace('a', 'b') // first match only str.replaceAll('a', 'b')
Slicing & splitting
str.slice(1, 4) // chars 1–3 str.slice(-3) // last 3 chars str.split(',') // array by delimiter str.split('') // array of chars str.repeat(3) // 'abc' → 'abcabcabc' str.padStart(5, '0') // '42' → '00042'
Template literal tags (tagged templates)
function highlight(strings, ...values) { return strings.reduce((result, str, i) => result + str + (values[i] ? `<b>${values[i]}</b>` : '') ); } const name = 'Alice'; highlight`Hello, ${name}!`;

Control Flow

Quick reference
Loop array
for (const item of arr) { }
Loop object
for (const [k, v] of Object.entries(obj)) { }
Try/catch
try { } catch (err) { }
Ternary
condition ? 'yes' : 'no'

Loops

beginner
for, for...of, for...in
// Classic for for (let i = 0; i < arr.length; i++) { } // for...of - iterables (arrays, strings, maps) for (const item of arr) { } // for...in - object keys (avoid for arrays) for (const key in obj) { if (obj.hasOwn(key)) { /*...*/ } }
while & do...while
while (condition) { /* check first */ } do { /* runs at least once */ } while (condition);
switch with fall-through guard
switch (status) { case 'active': case 'enabled': // fall-through handleActive(); break; case 'inactive': handleInactive(); break; default: handleUnknown(); }

Error Handling

beginner
try / catch / finally
try { riskyOperation(); } catch (err) { if (err instanceof TypeError) { // handle type errors } console.error(err.message); } finally { cleanup(); // always runs }
Custom error types
class AppError extends Error { constructor(message, code) { super(message); this.name = 'AppError'; this.code = code; } } throw new AppError('Not found', 404);

Async & Promises

Quick reference
Fetch JSON
await fetch(url).then(r => r.json())
Parallel await
await Promise.all([p1, p2])
All results
Promise.allSettled([p1, p2])
First to resolve
Promise.race([p1, p2])

Promises

intermediate
Creating and chaining promises
const p = new Promise((resolve, reject) => { if (ok) resolve(value); else reject(new Error('failed')); }); p.then(val => process(val)) .catch(err => handleErr(err)) .finally(() => cleanup());
Promise combinators
// All must resolve (fails fast) await Promise.all([p1, p2, p3]); // All settle - never throws const results = await Promise.allSettled([p1, p2]); results.filter(r => r.status === 'fulfilled'); // First to resolve await Promise.race([p1, timeout]); // First to resolve (ignores rejections) await Promise.any([p1, p2]);

async / await

intermediate
async function patterns
async function fetchUser(id) { const res = await fetch(`/api/users/${id}`); if (!res.ok) throw new Error(res.statusText); return res.json(); } // Arrow async const fetchUser = async (id) => { const res = await fetch(`/api/users/${id}`); return res.json(); };
Parallel vs sequential awaits
// Sequential - each waits for prior (slow) const a = await fetchA(); const b = await fetchB(); // Parallel - both run simultaneously (fast) const [a, b] = await Promise.all([fetchA(), fetchB()]);
Use Promise.all when operations are independent
Async iteration
async function* paginate(url) { let nextUrl = url; while (nextUrl) { const res = await fetch(nextUrl); const data = await res.json(); yield data.items; nextUrl = data.nextPage; } } for await (const items of paginate('/api/items')) { }

DOM Manipulation

Quick reference
Select element
document.querySelector('.sel')
Add listener
el.addEventListener('click', fn)
Toggle class
el.classList.toggle('active')
Insert HTML
el.insertAdjacentHTML('beforeend', html)

Selecting Elements

beginner
querySelector family
document.querySelector('.btn') // first match document.querySelectorAll('.item') // NodeList document.getElementById('main') // by id document.getElementsByClassName('x') // live HTMLCollection el.closest('.parent') // traverse up el.matches('.active') // test selector
Modifying elements
el.textContent = 'safe text'; // no HTML parsing el.innerHTML = '<b>bold</b>'; // parsed as HTML el.setAttribute('href', '/path'); el.removeAttribute('disabled'); el.classList.add('active'); el.classList.remove('active'); el.classList.toggle('active'); el.style.display = 'none';

Events

beginner
addEventListener options
el.addEventListener('click', handler); el.removeEventListener('click', handler); // Options el.addEventListener('click', handler, { once: true, // auto-remove after first call passive: true, // never calls preventDefault capture: false, // bubble phase (default) });
Event delegation
// One listener on parent instead of many children document.querySelector('#list') .addEventListener('click', e => { const item = e.target.closest('[data-id]'); if (!item) return; handleItem(item.dataset.id); });
More efficient than adding listeners to each child
Custom events
// Dispatch el.dispatchEvent(new CustomEvent('my-event', { detail: { userId: 42 }, bubbles: true, cancelable: true, })); // Listen el.addEventListener('my-event', e => { console.log(e.detail.userId); });

ES6+ Features

Quick reference
Array destructure
const [a, b, ...rest] = arr
Object rest
const { a, ...rest } = obj
ES Module import
import { fn } from './module.js'
Default export
export default function fn() {}

Destructuring & Spread

intermediate
Array destructuring & swap
const [first, second, ...rest] = arr; const [, , third] = arr; // skip elements // Swap variables let a = 1, b = 2; [a, b] = [b, a];
Spread operator uses
// Copy array / object const copy = [...arr]; const clone = { ...obj }; // Merge const merged = [...arr1, ...arr2]; const updated = { ...defaults, ...overrides }; // Spread into function Math.max(...nums); fn(...args);

Modules

intermediate
Named and default exports/imports
// math.js - named exports export const PI = 3.14; export function add(a, b) { return a + b; } export default class Calculator { } // main.js - importing import Calculator, { PI, add } from './math.js'; import * as math from './math.js'; // namespace
Dynamic import (code splitting)
// Load on demand const { add } = await import('./math.js'); // Conditional loading if (needsChart) { const { Chart } = await import('./chart.js'); new Chart(canvas); }

Classes

Quick reference
Basic class
class Animal { constructor(name) {} }
Extend class
class Dog extends Animal { }
Static method
static create(data) { }
Private field
#privateField = 'private'

Class Syntax

intermediate
Full class with getters, setters, static
class Person { #age; // private field static count = 0; constructor(name, age) { this.name = name; this.#age = age; Person.count++; } get age() { return this.#age; } set age(v) { if (v < 0) throw new RangeError('Invalid age'); this.#age = v; } static create(data) { return new Person(data.name, data.age); } }
Inheritance with super
class Animal { constructor(name) { this.name = name; } speak() { return `${this.name} makes a noise.`; } } class Dog extends Animal { constructor(name, breed) { super(name); // must call before this this.breed = breed; } speak() { return `${this.name} barks.`; } }
Mixins pattern
const Serializable = (Base) => class extends Base { toJSON() { return JSON.stringify(this); } static fromJSON(json) { return Object.assign(new this(), JSON.parse(json)); } }; class User extends Serializable(Person) { }

Advanced Patterns

Quick reference
Debounce
debounce(fn, 300)
Proxy object
new Proxy(obj, handler)
Generator
function* gen() { yield 1; }
Intersection Observer
new IntersectionObserver(cb)

Performance Patterns

advanced
Debounce & throttle
function debounce(fn, delay) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), delay); }; } function throttle(fn, limit) { let inThrottle; return (...args) => { if (!inThrottle) { fn(...args); inThrottle = true; setTimeout(() => (inThrottle = false), limit); } }; }
Generators & iterators
function* range(start, end, step = 1) { for (let i = start; i < end; i += step) { yield i; } } [...range(0, 10, 2)] // → [0, 2, 4, 6, 8] for (const n of range(1, 4)) { console.log(n); // 1, 2, 3 }

Proxy & Reflect

advanced
Proxy for validation & logging
const validator = { set(obj, prop, value) { if (prop === 'age' && typeof value !== 'number') { throw new TypeError('Age must be a number'); } obj[prop] = value; return true; // required } }; const person = new Proxy({}, validator); person.age = 30; // ok person.age = 'x'; // throws TypeError
WeakRef & FinalizationRegistry
const ref = new WeakRef(heavyObject); // Later: const obj = ref.deref(); if (obj) { /* still alive */ } const registry = new FinalizationRegistry(key => { console.log(`${key} was garbage collected`); }); registry.register(heavyObject, 'myObj');

Useful Patterns

intermediate
Observer / pub-sub pattern
class EventEmitter { #handlers = new Map(); on(event, fn) { if (!this.#handlers.has(event)) this.#handlers.set(event, []); this.#handlers.get(event).push(fn); } emit(event, data) { this.#handlers.get(event)?.forEach(fn => fn(data)); } off(event, fn) { const fns = this.#handlers.get(event) ?? []; this.#handlers.set(event, fns.filter(f => f !== fn)); } }
Pipe / compose functions
// pipe - left to right const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x); // compose - right to left const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x); const process = pipe(trim, toLowerCase, removeSpaces); process(' Hello World '); // → 'helloworld'

Most developers don't memorize everything. They keep a solid JavaScript cheat sheet nearby and look things up when needed. That's not a weakness - that's just how the job works.

JavaScript has a lot of moving parts. Arrow functions, array methods, DOM manipulation, async/await, ES6 destructuring. Keeping all of it in your head at once isn't realistic.

This guide covers the core syntax and methods you'll reach for constantly:

Bookmark it. Use it as your quick reference when you're mid-build and just need to check the syntax fast.

What is a JavaScript Cheat Sheet

A JavaScript cheat sheet is a condensed syntax reference that puts the core language in one place: variables, data types, functions, arrays, objects, loops, and events.

It's not a tutorial. No step-by-step explanations, no beginner hand-holding.

The point is fast lookup. You're mid-project, you can't remember how array destructuring syntax works, and you need the answer in ten seconds, not a 20-minute read.

JavaScript Variables and Data Types

How to Declare Variables in JavaScript

Three options: var, let, and const. In practice, var is legacy. You'll mostly see it in older codebases.

Use let when the value needs to change. Use const for everything else, which ends up being most declarations.

var name = 'Alice';       // function-scoped, hoisted
let count = 0;            // block-scoped, reassignable
const MAX_SIZE = 100;     // block-scoped, not reassignable

var vs let vs const: Scope Differences

Keyword

Scope

Hoisted

Reassignable

var

Function

Yes (undefined)

Yes

let

Block

No (TDZ)

Yes

const

Block

No (TDZ)

No

TDZ (Temporal Dead Zone): accessing let or const before declaration throws a ReferenceError.

With var, you just get undefined, which is its own kind of tricky.

JavaScript Primitive Data Types

Seven primitive types. Stored by value, not by reference. That distinction matters a lot once you start passing data between functions.

Type

Example

Notes

string

"hello", 'world'

Immutable. UTF-16 encoded.

number

42, 3.14, NaN

All numbers are 64-bit floats. NaN is technically a number.

bigint

9007199254740991n

Integers beyond Number.MAX_SAFE_INTEGER.

boolean

true / false

Logic and conditional checks.

undefined

undefined

Declared but never assigned.

null

null

Intentional absence of a value.

symbol

Symbol('id')

Unique identifiers. Rarely used directly.

typeof 'hello'       // 'string'
typeof 42            // 'number'
typeof true          // 'boolean'
typeof undefined     // 'undefined'
typeof null          // 'object'  <- known JS quirk
typeof Symbol()      // 'symbol'
typeof 42n           // 'bigint'

JavaScript Reference Data Types

Objects, Arrays, and Functions are reference types. Assign one to a new variable and both variables point to the same place in memory, not a copy.

const a = { x: 1 };
const b = a;
b.x = 99;
console.log(a.x);  // 99 - same object in memory

This trips up beginners constantly. To get an actual copy of an object, use the spread operator or Object.assign().

JavaScript Operators

Arithmetic Operators in JavaScript

Operator

Description

Example

Result

+

Addition

5 + 3

8

-

Subtraction

5 - 3

2

*

Multiplication

5 * 3

15

/

Division

10 / 3

3.333...

%

Modulus (remainder)

10 % 3

1

**

Exponentiation

2 ** 8

256

++

Increment

x++

x + 1

--

Decrement

x--

x - 1

Watch out with +: if either operand is a string, it concatenates instead of adding. '5' + 3 gives '53', not 8. Classic JS gotcha.

Comparison Operators in JavaScript

Always prefer === over == in production code. The loose equality operator performs type coercion, which produces genuinely confusing results.

Operator

Meaning

Example

Result

==

Loose equal (coerces type)

'5' == 5

true

===

Strict equal (no coercion)

'5' === 5

false

!=

Loose not equal

'5' != 5

false

!==

Strict not equal

'5' !== 5

true

>

Greater than

10 > 5

true

<

Less than

10 < 5

false

>=

Greater or equal

5 >= 5

true

<=

Less or equal

4 <= 5

true

Logical Operators in JavaScript

Operator

Name

Description

Example

&&

AND

True if both operands are truthy

true && falsefalse

||

OR

True if at least one operand is truthy

false || truetrue

!

NOT

Inverts the boolean value

!truefalse

Short-circuit evaluation: with &&, if the left side is falsy, the right side never runs.

With ||, if the left side is truthy, the right side is skipped. Useful for default values and conditional execution.

Nullish Coalescing and Optional Chaining

Both were added in ES2020. Both solve real problems that drove developers nuts for years.

// ?? returns the right side only when left is null or undefined
const port = userConfig.port ?? 3000;

// || would return 3000 even for port = 0 (falsy)
// ?? only triggers for null/undefined - much safer

// ?. stops execution if a property is null or undefined
const city = user?.address?.city;
// No TypeError if user or address doesn't exist. Just returns undefined.

JavaScript Strings

String Methods in JavaScript

Strings are immutable in JavaScript. Every method returns a new string. The original is never changed.

Method

What it does

Example

.length

Returns character count

'hello'.length5

.toUpperCase()

Converts to uppercase

'hi'.toUpperCase()'HI'

.toLowerCase()

Converts to lowercase

'HI'.toLowerCase()'hi'

.trim()

Removes whitespace from both ends

' hi '.trim()'hi'

.split(sep)

Splits into array by separator

'a,b'.split(',')['a','b']

.replace(a, b)

Replaces first match

'cat'.replace('c','b')'bat'

.replaceAll(a, b)

Replaces all matches

'aa'.replaceAll('a','b')'bb'

.includes(str)

Returns true if string contains str

'hello'.includes('ell')true

.indexOf(str)

Returns first index of str, or -1

'hello'.indexOf('l')2

.slice(s, e)

Extracts characters from index s to e

'hello'.slice(1,3)'el'

.substring(s, e)

Similar to slice, no negative indexes

'hello'.substring(1,3)'el'

.padStart(n, ch)

Pads string start to length n

'5'.padStart(3,'0')'005'

.repeat(n)

Repeats the string n times

'ab'.repeat(3)'ababab'

.startsWith(str)

Checks if string starts with str

'hello'.startsWith('he')true

.endsWith(str)

Checks if string ends with str

'hello'.endsWith('lo')true

.at(i)

Supports negative indexing

'hello'.at(-1)'o'

.charCodeAt(i)

Returns UTF-16 code at index i

'A'.charCodeAt(0)65

Template Literals in JavaScript

Template literals use backticks instead of quotes. They support string interpolation, multi-line strings, and tagged templates.

const name = 'Alice';
const age  = 30;

// Interpolation with ${}
const greeting = `Hello, ${name}. You are ${age} years old.`;

// Multi-line strings - newlines are preserved as-is
const html = `
  <div>
    <p>${name}</p>
  </div>
`;

// Expressions inside ${}
const msg = `Next year you'll be ${age + 1}`;

String Concatenation vs Template Literals

Template literals are cleaner for anything beyond a simple two-part join. Concatenation gets unreadable fast.

// Old way
const msg1 = 'Hello, ' + name + '. You are ' + age + ' years old.';

// Modern way
const msg2 = `Hello, ${name}. You are ${age} years old.`;

JavaScript Arrays

How to Create and Access Arrays in JavaScript

The array literal syntax is what you'll use 99% of the time. new Array() exists but there's almost never a reason to reach for it.

// Array literal (preferred)
const fruits = ['apple', 'banana', 'cherry'];

// Accessing by index (zero-based)
fruits[0]      // 'apple'
fruits[2]      // 'cherry'
fruits.at(-1)  // 'cherry' - negative indexing, ES2022

// Length
fruits.length  // 3

// Arrays can hold mixed types
const mixed = [1, 'two', true, null, { x: 3 }];

JavaScript Array Methods

Mutating Array Methods

These change the original array directly.

Method

What it does

Returns

.push(...items)

Adds items to the end

New length

.pop()

Removes last item

Removed item

.shift()

Removes first item

Removed item

.unshift(...items)

Adds items to the start

New length

.splice(i, n, ...a)

Removes n items at index i, optionally inserts a

Removed items

.sort(fn)

Sorts in place (default: alphabetical)

Sorted array

.reverse()

Reverses in place

Reversed array

.fill(val, s, e)

Fills index s to e with val

Modified array

.sort() defaults to alphabetical order, which means numbers sort wrong without a comparator.

[10, 9, 2].sort() gives [10, 2, 9]. Always pass a function for numeric sorting: arr.sort((a, b) => a - b).

Non-Mutating Array Methods

These return a new array and leave the original untouched. Prefer these in most cases.

Method

What it does

Returns

.map(fn)

Transforms each item via fn

New array (same length)

.filter(fn)

Keeps items where fn returns true

New array (shorter)

.reduce(fn, init)

Accumulates values into a single result

Single value

.find(fn)

Returns first item where fn is true

Item or undefined

.findIndex(fn)

Returns index of first match

Index or -1

.some(fn)

True if at least one item passes fn

Boolean

.every(fn)

True if all items pass fn

Boolean

.flat(depth)

Flattens nested arrays

New flat array

.flatMap(fn)

Maps then flattens one level

New array

.concat(...arrs)

Merges arrays

New merged array

.slice(s, e)

Extracts section from s to e

New array

.includes(item)

Checks if item exists

Boolean

.indexOf(item)

Returns first index of item

Index or -1

.join(sep)

Joins items into a string

String

.forEach(fn)

Runs fn for each item, no return value

undefined

const nums = [1, 2, 3, 4, 5];

nums.map(n => n * 2)                   // [2, 4, 6, 8, 10]
nums.filter(n => n % 2 === 0)          // [2, 4]
nums.reduce((acc, n) => acc + n, 0)    // 15
nums.find(n => n > 3)                  // 4
nums.some(n => n > 4)                  // true
nums.every(n => n > 0)                 // true

Destructuring Arrays in JavaScript

Array destructuring lets you pull values out by position and assign them to variables in one line.

const [first, second, third] = ['a', 'b', 'c'];
// first = 'a', second = 'b', third = 'c'

// Skipping elements
const [, , thirdOnly] = ['a', 'b', 'c'];
// thirdOnly = 'c'

// Default values
const [x = 10, y = 20] = [5];
// x = 5, y = 20

// Rest pattern - collects remaining items
const [head, ...tail] = [1, 2, 3, 4];
// head = 1, tail = [2, 3, 4]

// Swapping variables without a temp variable
let a = 1, b = 2;
[a, b] = [b, a];
// a = 2, b = 1

JavaScript Objects

How to Create Objects in JavaScript

The object literal is the standard. new Object() and Object.create() exist but you'll rarely need them outside specific inheritance patterns.

// Object literal (standard)
const user = {
  name: 'Alice',
  age: 30,
  isAdmin: false
};

// Constructor function
function User(name, age) {
  this.name = name;
  this.age = age;
}
const alice = new User('Alice', 30);

// Object.create() - sets prototype explicitly
const proto = { greet() { return `Hi, I'm ${this.name}`; } };
const bob = Object.create(proto);
bob.name = 'Bob';

Accessing and Modifying Object Properties

Dot notation is standard. Use bracket notation when the property name is dynamic or contains special characters.

const user = { name: 'Alice', age: 30 };

// Dot notation
user.name           // 'Alice'

// Bracket notation
user['age']         // 30
const key = 'name';
user[key]           // 'Alice'

// Adding a property
user.email = 'alice@example.com';

// Updating a property
user.age = 31;

// Deleting a property
delete user.isAdmin;

JavaScript Object Methods

Method

What it does

Object.keys(obj)

Returns array of own property names

Object.values(obj)

Returns array of own property values

Object.entries(obj)

Returns array of [key, value] pairs

Object.assign(target, src)

Copies properties from src into target

Object.freeze(obj)

Prevents any changes to the object

Object.isFrozen(obj)

Checks if object is frozen

Object.hasOwn(obj, key)

True if obj has the key as own property

Object.fromEntries(arr)

Creates object from [key, value] pairs

Destructuring Objects in JavaScript

Object destructuring pulls named properties into variables.

Unlike array destructuring, order doesn't matter. You match by property name.

const user = { name: 'Alice', age: 30, city: 'NYC' };

// Basic destructuring
const { name, age } = user;

// Renaming variables
const { name: userName, age: userAge } = user;

// Default values
const { role = 'viewer' } = user;
// role = 'viewer' (not in user object)

// Nested destructuring
const { address: { city, zip } } = { address: { city: 'NYC', zip: '10001' } };

// Rest pattern
const { name: n, ...rest } = user;
// rest = { age: 30, city: 'NYC' }

Spread Operator vs Object.assign

Both create shallow copies. The spread syntax is cleaner for most use cases.

const original = { a: 1, b: 2 };

// Spread (ES2018)
const copy1 = { ...original, c: 3 };
// { a: 1, b: 2, c: 3 }

// Object.assign
const copy2 = Object.assign({}, original, { c: 3 });
// { a: 1, b: 2, c: 3 }

Shallow copy means nested objects are still referenced, not duplicated. If you need a deep clone, use structuredClone() (ES2022) or JSON.parse(JSON.stringify(obj)) for simple data.

JavaScript Functions

Function Declaration vs Function Expression

Function declarations are hoisted. You can call them before they appear in the file.

Function expressions are not hoisted. Call them before the declaration and you get a TypeError.

// Declaration - hoisted
function greet(name) {
  return `Hello, ${name}`;
}

// Expression - not hoisted
const greet = function(name) {
  return `Hello, ${name}`;
};

// Named function expression
const greet = function greetUser(name) {
  return `Hello, ${name}`;
};

Arrow Functions in JavaScript

Arrow functions have shorter syntax and don't bind their own this. That second point is the one that actually matters.

// Standard function
function add(a, b) { return a + b; }

// Arrow - multiple params
const add = (a, b) => a + b;

// Arrow - single param, no parens needed
const double = n => n * 2;

// Arrow - no params
const greet = () => 'Hello';

// Arrow - block body (needs explicit return)
const add = (a, b) => {
  const result = a + b;
  return result;
};

Avoid arrow functions as object methods or constructors. this won't point where you expect.

Default Parameters and Rest Parameters

// Default parameters
function greet(name = 'stranger', greeting = 'Hello') {
  return `${greeting}, ${name}`;
}
greet()              // 'Hello, stranger'
greet('Alice')       // 'Hello, Alice'

// Rest parameters - collects remaining args into an array
function sum(...nums) {
  return nums.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3, 4)     // 10

Rest must be the last parameter. function fn(a, b, ...rest) is valid. function fn(...rest, a) throws a SyntaxError.

Higher-Order Functions in JavaScript

A higher-order function either takes a function as an argument or returns one. Most array methods are higher-order functions.

// Passing a function as an argument
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);   // [2, 4, 6]

// Returning a function (factory pattern)
function multiplier(factor) {
  return n => n * factor;
}
const triple = multiplier(3);
triple(5);   // 15

Callback Functions vs Promises

Callbacks work fine for simple async tasks. They get messy fast when you need to chain multiple async operations.

// Callback
fs.readFile('file.txt', (err, data) => {
  if (err) throw err;
  console.log(data);
});

// Promise - cleaner chaining
fetch('/api/user')
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

JavaScript Control Flow

if, else if, else Statements

const score = 75;

if (score >= 90) {
  console.log('A');
} else if (score >= 70) {
  console.log('C');
} else {
  console.log('F');
}

// Ternary - one-liner for simple conditions
const grade = score >= 70 ? 'Pass' : 'Fail';

switch Statements in JavaScript

Use switch when you're comparing one value against many possible matches. More readable than a long else if chain.

const day = 'Monday';

switch (day) {
  case 'Monday':
  case 'Tuesday':
    console.log('Weekday');
    break;
  case 'Saturday':
  case 'Sunday':
    console.log('Weekend');
    break;
  default:
    console.log('Unknown');
}

Always add break. Without it, execution falls through to the next case. Sometimes useful, usually a bug.

JavaScript Loops

for Loop

Standard loop. Use when you need the index or a fixed number of iterations.

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

for...of Loop

Cleanest way to iterate over arrays, strings, maps, and sets. No index access.

const fruits = ['apple', 'banana', 'cherry'];

for (const fruit of fruits) {
  console.log(fruit);
}

// Works on strings too
for (const char of 'hello') {
  console.log(char);   // h, e, l, l, o
}

for...in Loop

Iterates over the enumerable properties of an object. Not recommended for arrays.

const user = { name: 'Alice', age: 30 };

for (const key in user) {
  console.log(`${key}: ${user[key]}`);
}
// name: Alice
// age: 30

Avoid using for...in on arrays. It can pick up inherited prototype properties and the order isn't guaranteed.

while and do...while Loops

// while - checks condition before each iteration
let i = 0;
while (i < 3) {
  console.log(i);
  i++;
}

// do...while - runs at least once, checks after
let j = 0;
do {
  console.log(j);
  j++;
} while (j < 3);

break and continue in JavaScript

break exits the loop entirely. continue skips the current iteration and moves to the next.

for (let i = 0; i < 10; i++) {
  if (i === 5) break;      // stops at 5
  if (i % 2 === 0) continue; // skips even numbers
  console.log(i);          // 1, 3
}

In nested loops, break and continue only affect the innermost loop. Use labeled statements if you need to break out of an outer loop.

JavaScript Classes

How to Create a Class in JavaScript

Classes in JavaScript are syntactic sugar over the prototype system. The underlying mechanism is the same, the syntax is just cleaner.

class Animal {
  constructor(name, sound) {
    this.name = name;
    this.sound = sound;
  }

  speak() {
    return `${this.name} says ${this.sound}`;
  }
}

const dog = new Animal('Dog', 'woof');
dog.speak();   // 'Dog says woof'

Class Inheritance in JavaScript

Use extends to inherit from a parent class. Call super() inside the constructor before accessing this.

class Dog extends Animal {
  constructor(name) {
    super(name, 'woof');   // calls Animal constructor
    this.type = 'domestic';
  }

  fetch(item) {
    return `${this.name} fetches the ${item}`;
  }
}

const rex = new Dog('Rex');
rex.speak();       // 'Rex says woof'  (inherited)
rex.fetch('ball'); // 'Rex fetches the ball'

Static Methods and Properties

Static members belong to the class itself, not to instances. Use them for utility functions that don't need instance data.

class MathHelper {
  static PI = 3.14159;

  static square(n) {
    return n * n;
  }
}

MathHelper.square(4);   // 16
MathHelper.PI;          // 3.14159

// Calling on an instance throws TypeError
const m = new MathHelper();
m.square(4);   // TypeError

Class vs Constructor Function

Classes and constructor functions produce the same result. Classes are just cleaner to read and write.

// Constructor function
function Person(name) {
  this.name = name;
}
Person.prototype.greet = function() {
  return `Hi, I'm ${this.name}`;
};

// Class equivalent
class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    return `Hi, I'm ${this.name}`;
  }
}

JavaScript Promises and Async/Await

How Promises Work in JavaScript

A Promise represents a value that isn't available yet. It's either pending, fulfilled, or rejected.

const promise = new Promise((resolve, reject) => {
  const success = true;
  if (success) {
    resolve('Data loaded');
  } else {
    reject(new Error('Something failed'));
  }
});

promise
  .then(data => console.log(data))      // 'Data loaded'
  .catch(err => console.error(err))
  .finally(() => console.log('Done'));  // always runs

async/await Syntax in JavaScript

async/await is built on top of Promises. It makes async code read like synchronous code.

async function fetchUser(id) {
  try {
    const res = await fetch(`/api/users/${id}`);
    const data = await res.json();
    return data;
  } catch (err) {
    console.error('Request failed:', err);
  }
}

An async function always returns a Promise, even if you return a plain value. await can only be used inside an async function (or at the top level of a module in modern JS).

Promise.all, Promise.race, Promise.allSettled

Method

Behavior

Promise.all(arr)

Resolves when all resolve. Rejects if any one rejects.

Promise.race(arr)

Resolves or rejects as soon as the first one settles.

Promise.allSettled(arr)

Waits for all, returns each result regardless of outcome.

Promise.any(arr)

Resolves as soon as any one resolves. Ignores rejections.

const [user, posts] = await Promise.all([
  fetch('/api/user').then(r => r.json()),
  fetch('/api/posts').then(r => r.json())
]);

Promise.all is the one you'll use most. Good for parallel requests where you need all results.

JavaScript Error Handling

try/catch/finally in JavaScript

try {
  const data = JSON.parse(invalidJSON);
} catch (err) {
  console.error(err.message);
} finally {
  console.log('Always runs - cleanup goes here');
}

finally runs whether or not an error was thrown. Use it for cleanup like closing connections or hiding loading spinners.

Error Types in JavaScript

Error Type

When it appears

SyntaxError

Invalid JavaScript syntax (caught at parse time)

TypeError

Operation on wrong type (null.property)

ReferenceError

Accessing an undeclared variable

RangeError

Value outside allowed range (new Array(-1))

URIError

Malformed URI in decodeURIComponent()

EvalError

Issues with eval() (rare in modern code)

TypeError and ReferenceError are the ones you'll see most often in day-to-day JavaScript development.

Custom Errors in JavaScript

Extend the built-in Error class to create custom error types with specific names and behavior.

class ValidationError extends Error {
  constructor(message, field) {
    super(message);
    this.name = 'ValidationError';
    this.field = field;
  }
}

try {
  throw new ValidationError('Email is required', 'email');
} catch (err) {
  if (err instanceof ValidationError) {
    console.log(`${err.name} on field: ${err.field}`);
  }
}

JavaScript Modules

export and import in JavaScript

ES modules are the standard module system. Supported natively in browsers and Node.js.

// math.js - named exports
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }

// Default export - one per file
export default function multiply(a, b) { return a * b; }
// main.js - importing
import multiply, { PI, add } from './math.js';

// Import everything as a namespace
import * as Math from './math.js';
Math.add(2, 3);   // 5

// Rename on import
import { add as sum } from './math.js';

Dynamic Imports in JavaScript

import() loads a module on demand instead of upfront. Useful for lazy loading large features or routes.

// Static import (loads at startup)
import { heavyFunction } from './heavy.js';

// Dynamic import (loads only when needed)
async function loadChart() {
  const { renderChart } = await import('./chart.js');
  renderChart(data);
}

button.addEventListener('click', loadChart);

Returns a Promise. Works anywhere, not just at the top level of a file.

JavaScript DOM Manipulation

How to Select DOM Elements

// Single element
document.getElementById('header')
document.querySelector('.nav-link')      // first match
document.querySelector('#app > div')    // CSS selector

// Multiple elements
document.querySelectorAll('.card')      // NodeList
document.getElementsByClassName('btn') // HTMLCollection
document.getElementsByTagName('p')     // HTMLCollection

querySelector and querySelectorAll accept any valid CSS selector. Use these over the older methods in most cases.

Modifying DOM Elements

const el = document.querySelector('#title');

// Content
el.textContent = 'Hello';          // plain text, safe
el.innerHTML   = '<b>Hello</b>';   // parses HTML - careful with user input

// Attributes
el.setAttribute('data-id', '42');
el.getAttribute('data-id');        // '42'
el.removeAttribute('data-id');

// Inline styles
el.style.color = 'red';
el.style.fontSize = '18px';

// Classes
el.classList.add('active');
el.classList.remove('hidden');
el.classList.toggle('open');
el.classList.contains('active');   // true/false

Creating and Removing DOM Elements

// Create
const div = document.createElement('div');
div.textContent = 'New element';
div.classList.add('card');

// Insert
document.body.appendChild(div);
parent.insertBefore(div, referenceNode);
parent.append(div);           // modern, accepts strings too
parent.prepend(div);

// Remove
div.remove();                 // modern
parent.removeChild(div);      // older API

JavaScript Event Listeners

const btn = document.querySelector('#submit');

// Add listener
btn.addEventListener('click', handleClick);

function handleClick(event) {
  event.preventDefault();
  console.log('Clicked:', event.target);
}

// Remove listener - must use the same function reference
btn.removeEventListener('click', handleClick);

// Common event types
// click, dblclick, mouseenter, mouseleave
// keydown, keyup, keypress
// input, change, submit, focus, blur
// load, DOMContentLoaded, resize, scroll

Use event.preventDefault() to stop default browser behavior (form submission, link navigation).

Use event.stopPropagation() to prevent the event from bubbling up to parent elements.

JavaScript ES6+ Features

JavaScript Symbols

Symbols are unique, immutable identifiers. Two symbols with the same description are never equal.

const id1 = Symbol('id');
const id2 = Symbol('id');
id1 === id2   // false - always unique

// Common use: unique object keys that won't clash
const KEY = Symbol('key');
obj[KEY] = 'value';

WeakMap and WeakSet

WeakMap and WeakSet hold weak references. If the key (WeakMap) or value (WeakSet) is garbage collected, the entry disappears automatically.

const cache = new WeakMap();

function process(obj) {
  if (cache.has(obj)) return cache.get(obj);
  const result = heavyComputation(obj);
  cache.set(obj, result);
  return result;
}

Good for caching or metadata storage tied to object lifetimes. Not iterable.

Generators and Iterators

A generator function returns an iterator that produces values on demand. Uses function* syntax and yield.

function* range(start, end) {
  for (let i = start; i <= end; i++) {
    yield i;
  }
}

const nums = range(1, 5);
nums.next()   // { value: 1, done: false }
nums.next()   // { value: 2, done: false }

// Use with for...of
for (const n of range(1, 3)) {
  console.log(n);   // 1, 2, 3
}

Proxy and Reflect

Proxy intercepts and redefines operations on an object. Reflect provides the default behavior for those same operations.

const handler = {
  get(target, key) {
    return key in target ? target[key] : `Property "${key}" not found`;
  },
  set(target, key, value) {
    if (typeof value !== 'number') throw new TypeError('Numbers only');
    target[key] = value;
    return true;
  }
};

const proxy = new Proxy({}, handler);
proxy.x = 10;
proxy.x        // 10
proxy.missing  // 'Property "missing" not found'

Logical Assignment Operators

Introduced in ES2021. Combine a logical operation with assignment in one expression.

// ??= assigns only if left side is null or undefined
user.name ??= 'Anonymous';

// ||= assigns only if left side is falsy
config.timeout ||= 3000;

// &&= assigns only if left side is truthy
user.isAdmin &&= checkPermissions(user);

JavaScript Type Coercion and Comparison

Implicit vs Explicit Type Conversion

Implicit coercion happens automatically. Explicit conversion is intentional, using Number(), String(), Boolean().

// Implicit - JS converts types for you
'5' + 2        // '52' (number → string)
'5' - 2        // 3   (string → number)
true + 1       // 2   (boolean → number)

// Explicit - you control the conversion
Number('42')   // 42
Number(true)   // 1
Number(null)   // 0
Number('')     // 0
Number('abc')  // NaN

String(42)     // '42'
Boolean(0)     // false
Boolean('hi')  // true

Truthy and Falsy Values in JavaScript

Every value in JavaScript is either truthy or falsy in a boolean context.

Falsy values (all 8 of them):

false
0
-0
0n          // BigInt zero
''          // empty string
null
undefined
NaN

Everything else is truthy. [], {}, '0', and 'false' are all truthy. That last one trips people up.

Why null == undefined is true but null === undefined is false

Loose equality (==) treats null and undefined as equal to each other, and only to each other. No other value is loosely equal to null.

null == undefined    // true
null === undefined   // false  (different types)
null == 0            // false
null == ''           // false
null == false        // false

Practical rule: use == null as a shorthand to check for both null and undefined at once.

JavaScript Scope and Closures

Global Scope vs Local Scope vs Block Scope

Variables declared with var at the top level go on the global object (window in browsers).

let and const at the top level don't attach to window, but they're still globally accessible within the module.

var globalVar = 'I am global';   // window.globalVar in browsers

function localScope() {
  var localVar = 'only inside function';
  let blockLet = 'also only inside function';
}

{
  let blockScoped = 'only inside this block';
  var notBlockScoped = 'leaks out of block';
}
// blockScoped - ReferenceError
// notBlockScoped - accessible (var ignores blocks)

Closures in JavaScript

A closure is a function that retains access to its outer scope even after the outer function has returned.

function counter() {
  let count = 0;
  return {
    increment() { count++; },
    decrement() { count--; },
    value()     { return count; }
  };
}

const c = counter();
c.increment();
c.increment();
c.value();   // 2
// count is private - not accessible from outside

Common Closure Mistakes in JavaScript

The classic loop variable capture bug. Every callback ends up using the final value of i.

// Bug - all log 3
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}

// Fix 1 - use let (block scoped, new binding per iteration)
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);   // 0, 1, 2
}

// Fix 2 - IIFE to capture the value
for (var i = 0; i < 3; i++) {
  ((j) => setTimeout(() => console.log(j), 100))(i);
}

JavaScript this Keyword

How this Works in Different Contexts

this is determined by how a function is called, not where it's defined. That's the thing most people get wrong at first.

Context

this refers to

Global scope (non-strict)

window (browser) / global (Node.js)

Global scope (strict mode)

undefined

Object method

The object the method is called on

Constructor (new)

The newly created instance

Arrow function

Inherited from surrounding lexical scope

Event listener

The element that fired the event

const user = {
  name: 'Alice',
  greet() {
    console.log(this.name);   // 'Alice'
  },
  greetArrow: () => {
    console.log(this.name);   // undefined - arrow inherits outer this
  }
};

call, apply, and bind in JavaScript

All three let you explicitly set what this refers to inside a function.

function greet(greeting, punctuation) {
  return `${greeting}, ${this.name}${punctuation}`;
}

const user = { name: 'Alice' };

// call - args passed individually
greet.call(user, 'Hello', '!');       // 'Hello, Alice!'

// apply - args passed as array
greet.apply(user, ['Hello', '!']);    // 'Hello, Alice!'

// bind - returns new function with this permanently set
const greetAlice = greet.bind(user);
greetAlice('Hi', '.');                // 'Hi, Alice.'

bind is useful when passing methods as callbacks. Without it, this gets lost when the function is called outside its object context.

FAQ on Javascript Cheat Sheets

What should a JavaScript cheat sheet include?

A solid JavaScript syntax reference covers variables, data types, operators, arrays, objects, functions, loops, classes, promises, and ES6+ features.

The more useful ones also include code examples, not just syntax listings.

What is the difference between == and === in JavaScript?

== uses type coercion, so '5' == 5 returns true.

Strict equality (===) compares both value and type with no conversion. '5' === 5 returns false. Use === by default.

What are the most important JavaScript array methods to know?

.map(), .filter(), and .reduce() are the three you'll use constantly.

After those, .find(), .some(), .every(), and .flat() cover most real-world needs. All are non-mutating - they return new arrays.

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

var is function-scoped and hoisted. let and const are block-scoped and not hoisted.

Use const by default, let when the value needs to change. Avoid var in modern JavaScript.

What does this mean in JavaScript?

this refers to the object that called the function. It changes depending on the call context.

In arrow functions, this is inherited from the surrounding scope. In event listeners, it refers to the element that fired the event.

What is a closure in JavaScript?

A closure is a function that keeps access to variables from its outer scope even after that scope has closed.

Common uses include private variables, factory functions, and callback patterns. The counter function pattern is the most frequently cited example.

What is the difference between null and undefined?

undefined means a variable was declared but never assigned a value.

null is an intentional assignment - it signals the deliberate absence of a value. Both are falsy, but typeof null returns 'object', which is a known JavaScript quirk.

What are JavaScript template literals?

Template literals use backticks and support string interpolation via ${}, multi-line strings, and embedded expressions.

They replaced messy string concatenation in ES6. \Hello, ${nameis cleaner and easier to read than'Hello, ' + name.

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

.map() returns a new array with transformed values. .forEach() returns undefined - it just runs a function on each item.

Use .map() when you need the result. Use .forEach() when you only need the side effect.

What is async/await in JavaScript?

async/await is syntax built on top of Promises that makes asynchronous code read like synchronous code.

An async function always returns a Promise. await pauses execution until the Promise resolves, and errors are handled with standard try/catch blocks.