JavaScript Cheat Sheet
Every method, pattern, and ES6+ feature. Searchable, filterable by level, copy-ready.
Variables & Data Types
Declarations
Operators & Equality
Functions
Function Types
Closures & Scope
Arrays
Core Methods
Sorting & Transforming
Objects
Creating & Accessing
Map & Set
Strings
String Methods
Control Flow
Loops
Error Handling
Async & Promises
Promises
async / await
DOM Manipulation
Selecting Elements
Events
ES6+ Features
Destructuring & Spread
Modules
Classes
Class Syntax
Advanced Patterns
Performance Patterns
Proxy & Reflect
Useful Patterns
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:
-
Variables, data types, and type conversion
-
String and array methods
-
Loops, conditionals, and functions
-
ES6+ features like template literals and the spread operator
-
DOM events and basic error handling
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 |
|
Immutable. UTF-16 encoded. |
|
number |
|
All numbers are 64-bit floats. NaN is technically a number. |
|
bigint |
|
Integers beyond |
|
boolean |
|
Logic and conditional checks. |
|
undefined |
|
Declared but never assigned. |
|
null |
|
Intentional absence of a value. |
|
symbol |
|
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 |
|
|
|
|
Subtraction |
|
|
|
|
Multiplication |
|
|
|
|
Division |
|
|
|
|
Modulus (remainder) |
|
|
|
|
Exponentiation |
|
|
|
|
Increment |
|
|
|
|
Decrement |
|
|
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) |
|
|
|
|
Strict equal (no coercion) |
|
|
|
|
Loose not equal |
|
|
|
|
Strict not equal |
|
|
|
|
Greater than |
|
|
|
|
Less than |
|
|
|
|
Greater or equal |
|
|
|
|
Less or equal |
|
|
Logical Operators in JavaScript
|
Operator |
Name |
Description |
Example |
|---|---|---|---|
|
|
AND |
True if both operands are truthy |
|
|
|
OR |
True if at least one operand is truthy |
|
|
|
NOT |
Inverts the boolean value |
|
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 |
|---|---|---|
|
|
Returns character count |
|
|
|
Converts to uppercase |
|
|
|
Converts to lowercase |
|
|
|
Removes whitespace from both ends |
|
|
|
Splits into array by separator |
|
|
|
Replaces first match |
|
|
|
Replaces all matches |
|
|
|
Returns true if string contains str |
|
|
|
Returns first index of str, or -1 |
|
|
|
Extracts characters from index s to e |
|
|
|
Similar to slice, no negative indexes |
|
|
|
Pads string start to length n |
|
|
|
Repeats the string n times |
|
|
|
Checks if string starts with str |
|
|
|
Checks if string ends with str |
|
|
|
Supports negative indexing |
|
|
|
Returns UTF-16 code at index i |
|
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 |
|---|---|---|
|
|
Adds items to the end |
New length |
|
|
Removes last item |
Removed item |
|
|
Removes first item |
Removed item |
|
|
Adds items to the start |
New length |
|
|
Removes n items at index i, optionally inserts a |
Removed items |
|
|
Sorts in place (default: alphabetical) |
Sorted array |
|
|
Reverses in place |
Reversed array |
|
|
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 |
|---|---|---|
|
|
Transforms each item via fn |
New array (same length) |
|
|
Keeps items where fn returns true |
New array (shorter) |
|
|
Accumulates values into a single result |
Single value |
|
|
Returns first item where fn is true |
Item or undefined |
|
|
Returns index of first match |
Index or -1 |
|
|
True if at least one item passes fn |
Boolean |
|
|
True if all items pass fn |
Boolean |
|
|
Flattens nested arrays |
New flat array |
|
|
Maps then flattens one level |
New array |
|
|
Merges arrays |
New merged array |
|
|
Extracts section from s to e |
New array |
|
|
Checks if item exists |
Boolean |
|
|
Returns first index of item |
Index or -1 |
|
|
Joins items into a string |
String |
|
|
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 |
|---|---|
|
|
Returns array of own property names |
|
|
Returns array of own property values |
|
|
Returns array of |
|
|
Copies properties from src into target |
|
|
Prevents any changes to the object |
|
|
Checks if object is frozen |
|
|
True if obj has the key as own property |
|
|
Creates object from |
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 |
|---|---|
|
|
Resolves when all resolve. Rejects if any one rejects. |
|
|
Resolves or rejects as soon as the first one settles. |
|
|
Waits for all, returns each result regardless of outcome. |
|
|
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 |
|---|---|
|
|
Invalid JavaScript syntax (caught at parse time) |
|
|
Operation on wrong type ( |
|
|
Accessing an undeclared variable |
|
|
Value outside allowed range ( |
|
|
Malformed URI in |
|
|
Issues with |
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 |
|
|---|---|
|
Global scope (non-strict) |
|
|
Global scope (strict mode) |
|
|
Object method |
The object the method is called on |
|
Constructor ( |
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.