Programming cheat sheet

Practical JavaScript cheat sheet

Compact patterns for everyday JavaScript, with the traps that matter when values cross a form, URL, API, clock, or asynchronous boundary.

· About 12 minutes

Declare values with the narrowest mutation

const taxRate = 0.08;
let total = 0;

total += 25;

Use const when the binding will not be reassigned and let when reassignment is required. A const object can still have mutable properties; the binding is constant, not the object. Avoid var in new code unless its function scope and hoisting behavior are deliberately needed.

Know the primitive types

typeof "text"       // "string"
typeof 42           // "number"
typeof 42n          // "bigint"
typeof true         // "boolean"
typeof undefined    // "undefined"
typeof Symbol()     // "symbol"
typeof null         // "object" (a historical exception)

Objects, arrays, functions, dates, maps, and sets are reference values. Use Array.isArray(value) to identify arrays. Use value === null for null rather than relying on typeof.

Prefer strict equality

0 === false       // false
0 == false        // true because == coerces types
Number("42")      // 42
String(42)        // "42"

=== and !== compare without the broad coercion performed by == and !=. Convert at an input boundary when conversion is intended. Remember that NaN === NaN is false; use Number.isNaN(value). The MDN language overview provides a concise description of types and operators.

Separate missing, null, false, zero, and empty text

const label = inputLabel ?? "Untitled";
const visible = settings.visible ?? true;

// || would replace 0, false, and "" too.
const quantity = suppliedQuantity ?? 0;

Nullish coalescing (??) uses the fallback only for null or undefined. Logical OR (||) uses it for every falsy value, including zero, false, an empty string, and NaN. Optional chaining such as user.profile?.name stops when a link is nullish.

Transform arrays intentionally

const prices = [12, 5, 20];
const taxed = prices.map((price) => price * 1.08);
const large = prices.filter((price) => price >= 10);
const firstLarge = prices.find((price) => price >= 10);
const total = prices.reduce((sum, price) => sum + price, 0);
const sorted = [...prices].sort((a, b) => a - b);

map creates one output for each input, filter selects zero or more values, find returns the first match or undefined, and reduce combines values. Supply an initial value to reduce when an empty array is possible. sort mutates the array and sorts as strings without a comparator; copy first when the original order matters. See the MDN Array reference for copying and mutating methods.

Copy objects at the depth you mean

const updated = { ...user, name: "Ada" };
const tags = [...user.tags, "editor"];

// Nested objects remain shared in a shallow copy.
const shallow = { ...user };

Spread syntax makes a shallow copy. If user.profile is an object, both the original and shallow copy still point to the same nested profile. Use an explicit nested copy or a suitable structured-clone strategy when independent nested data is required.

Destructure with clear defaults

const { name, role = "reader" } = user;
const [first, second] = items;

function greet({ name = "friend" } = {}) {
  return `Hello, ${name}`;
}

A destructuring default applies when the property is undefined, not when it is null. The default empty object in the function parameter prevents a call with no argument from throwing.

Use errors for failed operations

function parsePositive(value) {
  const number = Number(value);
  if (!Number.isFinite(number) || number <= 0) {
    throw new RangeError("Expected a positive finite number");
  }
  return number;
}

try {
  const amount = parsePositive(input.value);
} catch (error) {
  console.error(error.message);
}

Validate at boundaries and throw an Error subclass with a useful message. Catch where the program can add context, recover, or communicate failure. Avoid catching an error only to ignore it.

Await asynchronous work and check protocol errors

async function loadUser(id) {
  const response = await fetch(`/api/users/${encodeURIComponent(id)}`);
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
}

try {
  const user = await loadUser("a/b");
} catch (error) {
  console.error("Could not load user", error);
}

await pauses only the dependent async flow; it does not block the whole runtime. A fulfilled fetch promise can still represent an HTTP error, so inspect response.ok. Independent promises can often run together with Promise.all, but one rejection rejects the combined promise. The MDN promises guide covers chaining, error handling, and composition.

Parse and serialize JSON defensively

const data = JSON.parse(text);
const compact = JSON.stringify(data);
const readable = JSON.stringify(data, null, 2);

JSON requires double-quoted strings and property names and does not support comments, trailing commas, undefined, functions, NaN, or Infinity. Parsing can throw SyntaxError. Very large numeric identifiers can lose precision when converted to JavaScript numbers; retain them as strings when exact digits matter. The MDN JSON.parse reference explains revivers and numeric precision. Use the local JSON Formatter to inspect syntax without uploading text.

Encode URL components, not entire structures

const query = new URLSearchParams({ q: "café & tools" });
query.toString(); // q=caf%C3%A9+%26+tools

const segment = encodeURIComponent("a/b"); // a%2Fb

encodeURIComponent is appropriate for one path or query value because it escapes structural separators. URLSearchParams manages query pairs and form-style spaces. Do not concatenate untrusted values into a URL and assume percent encoding validates the destination. The URL Encoder and Decoder makes component and complete-URL modes explicit.

Use timezone-explicit dates

const instant = new Date("2026-01-01T00:00:00Z");
instant.getTime();       // epoch milliseconds
instant.toISOString();   // UTC text

JavaScript Date stores an instant as milliseconds from the epoch. Display methods can use the local timezone. Prefer the standardized date-time string with Z or an explicit offset when an instant must be portable; nonstandard strings can parse differently between engines. MDN documents this portability concern in Date.parse. The Unix Timestamp Converter helps reveal seconds-versus-milliseconds errors.

Debug values, types, and timing

console.table(records);
console.log({ value, type: typeof value });
console.time("transform");
const output = transform(input);
console.timeEnd("transform");
debugger;

Log an object containing both the value and type when coercion is suspected. Use breakpoints to inspect state before it changes. Reproduce with the smallest input that still fails, then add a test for that input. For async bugs, log when a promise is created, awaited, fulfilled, or rejected rather than assuming visual code order equals completion order.

Keep the runtime in mind

JavaScript the language does not itself define the DOM, fetch, files, timers, or Node.js modules; runtimes provide those APIs. Check the target browser or Node version before using a feature. The MDN JavaScript Guide is a maintained starting point for the language, while each runtime documents its own APIs.

This cheat sheet is an original practical summary, not a complete specification or security review. Confirm compatibility, input trust, performance, and runtime behavior in the environment where code will run.