Emergency server help: get in touch

JavaScript Cheat Sheet: Modern Syntax for Browser and Node

A compact reference for modern JavaScript (ES2024 and later) in the browser and Node.js, with the language examples run on Node.js 24.

Published 8 min read

Short answer: Modern JavaScript uses const and let instead of var, === for comparisons, ?? and ?. for missing values, template literals for strings, and array methods such as map, filter and toSorted. Asynchronous code uses async/await with fetch, and code is split into ES modules with import and export. Recent additions include Object.groupBy, Set methods and iterator helpers, all available in Node.js 24 and current browsers.

The language and Node.js examples in this JavaScript cheat sheet were run with Node.js 24.21.0 (the current LTS line) on 9 October 2026. The browser DOM examples were checked against the MDN reference, not run.

Variables, types and operators

SyntaxWhat it doesResult
const host = "web01"Block-scoped constant binding (the object it points to can still change)
let count = 0Block-scoped variable you can reassign. Avoid var
typeof null · typeof []Two classic traps: both report object"object"
Array.isArray(x)The correct way to test for an arraytrue/false
0 == "" · 0 === ""Loose vs strict equality. Use ===true · false
cfg.port || 3306Fallback for any falsy value, including 0 and ""3306 if port is 0
cfg.port ?? 3306Fallback only for null or undefined0 if port is 0
cfg.nested?.deepOptional chaining: undefined instead of a TypeErrorundefined
x ??= 5 · x ||= "default"Assign only if nullish · if falsy
Number("42px") · parseInt("42px", 10)Strict vs lenient number parsingNaN · 42
Number.isNaN(x)NaN test (NaN === NaN is false)
(0.1 + 0.2).toFixed(2)Round for display; returns a string"0.30"
2n ** 64nBigInt for integers above Number.MAX_SAFE_INTEGER18446744073709551616n

Strings and template literals

SyntaxWhat it does
`${name}:${port}`Template literal: insert expressions; can span lines
s.split(",") · arr.join("-")String to array and back
s.trim() · s.trimStart() · s.trimEnd()Remove whitespace
s.includes("ell") · s.startsWith("he") · s.endsWith(".log")Substring tests
s.slice(1, 3) · s.at(-1)Substring by index · last character
s.replaceAll("b", "B")Replace every occurrence (replace with a string changes only the first)
s.replace(/[-_]/g, " ")Regex replace; the g flag means all matches
s.padStart(5, "0")Pad to a width
s.toUpperCase() · s.toLowerCase()Change case
new Intl.NumberFormat("en-GB").format(1234567.8)Locale-aware number: 1,234,567.8

Arrays

SyntaxWhat it does
nums.map(n => n * 2)New array with each item transformed
nums.filter(n => n > 2)New array with matching items
nums.reduce((sum, n) => sum + n, 0)Fold into one value; always pass the start value
nums.find(fn) · nums.findIndex(fn) · nums.findLast(fn)First match · its index · last match
nums.some(fn) · nums.every(fn) · nums.includes(4)Any match · all match · contains value
nums.push(x) · nums.pop() · nums.unshift(x) · nums.shift()Add or remove at the end · at the start (these change the array)
nums.sort((a, b) => a - b)Sort numbers in place. Without a compare function, [10, 9, 1].sort() gives [1, 10, 9]
nums.toSorted(fn) · nums.toReversed() · nums.with(0, 99)Copying versions that leave the original unchanged (ES2023)
nums.at(-1)Last item
nums.slice(1, 3)Copy of a range (splice changes the array)
[[1, 2], [3]].flat() · arr.flatMap(fn)Flatten one level · map then flatten
[...new Set(arr)]Remove duplicates
Array.from({ length: 3 }, (_, i) => i * i)Build an array: [0, 1, 4]
for (const [i, v] of arr.entries())Loop with index and value

Objects, destructuring and spread

const server = { name: "web01", ip: "10.0.0.5", tags: ["prod"] };

const { name, ip, os = "linux", ...rest } = server;   // rename with { name: srvName }
const [first, , third = "def", ...others] = [1, 2, undefined, 4, 5];

const copy = { ...server, ip: "10.0.0.6" };   // shallow copy with one change
const deep = structuredClone(server);         // deep copy (nested arrays too)

Object.keys(server);      // ["name", "ip", "tags"]
Object.entries(server);   // [["name", "web01"], ...]
Object.fromEntries([["a", 1]]);
Object.hasOwn(server, "ip");   // true

const map = new Map([["a", 1]]);   // any key type, keeps insertion order
map.set("b", 2); map.get("b"); map.has("a"); map.size;

JSON.stringify(server, null, 2);   // pretty JSON
JSON.parse('{"port": 3306}').port;

A spread copy is shallow: copy.tags is the same array as server.tags. Use structuredClone() when nested data must not be shared.

Functions and classes

function connect(host, port = 22, ...rest) { return `${host}:${port}`; }
const add = (a, b) => a + b;
const makeObj = () => ({ ok: true });      // wrap an object literal in brackets

class Server {
  #secret = "s3cret";                      // private field
  static count = 0;

  constructor(name, ip) {
    this.name = name;
    this.ip = ip;
    Server.count++;
  }
  get fqdn() { return `${this.name}.example.com`; }
  static fromLine(line) { return new Server(...line.split(" ")); }
}

class WebServer extends Server {
  constructor(name, ip, vhosts = 0) {
    super(name, ip);                       // must run before using this
    this.vhosts = vhosts;
  }
}

Arrow functions do not have their own this, so use them for callbacks and normal methods for class behaviour. A function that returns another function keeps access to its outer variables (a closure), which is how counters and simple caches are built.

Promises, async and fetch

SyntaxWhat it does
async function f() { const r = await g(); }Wait for a promise without callbacks
try { await f(); } catch (e) { ... } finally { ... }Handle a rejected promise
await Promise.all([a(), b()])Run in parallel; rejects on the first failure
await Promise.allSettled([...])Wait for all; each result has status fulfilled or rejected
await Promise.any([...]) · await Promise.race([...])First success · first to settle
const { promise, resolve, reject } = Promise.withResolvers()Create a promise and its controls in one step (ES2024)
p.then(v => ...).catch(e => ...).finally(() => ...)Chained form
new Promise(r => setTimeout(r, ms))A simple sleep
const res = await fetch("https://api.example.com/status", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ host: "web01" }),
  signal: AbortSignal.timeout(5000),        // give up after 5 seconds
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);   // fetch does not reject on 404 or 500
const data = await res.json();

Modules

SyntaxWhat it does
export function slug(s) { ... }Named export
export default class Logger { ... }Default export (one per module)
import Logger, { slug, VERSION as V } from "./util.mjs"Default plus named imports, with a rename
import * as util from "./util.mjs"Everything as one namespace object
const mod = await import("./util.mjs")Dynamic import, loaded on demand
import config from "./config.json" with { type: "json" }JSON module with an import attribute (ES2025)
import { readFile } from "node:fs/promises"Node built-in module; the node: prefix is explicit

In Node.js, files ending in .mjs, or .js files in a package with "type": "module", are ES modules. Top-level await works only in modules. In the browser, load them with <script type="module" src="app.js"></script>.

Newer built-ins: ES2023 and later

FeatureExampleSince
Group items by a keyObject.groupBy(rows, r => r.type)ES2024
Group into a MapMap.groupBy(nums, n => n % 2 ? "odd" : "even")ES2024
Set operationsa.union(b) · a.intersection(b) · a.difference(b) · a.isSubsetOf(b)ES2025
Iterator helpers (lazy)gen().filter(fn).map(fn).take(3).toArray()ES2025
Wrap any iterableIterator.from(arr).drop(1).toArray()ES2025
Escape text for a regexnew RegExp(RegExp.escape("1.2.3.4"))ES2025
Run sync or async code as a promisePromise.try(() => mayThrow())ES2025
Collect an async iterableawait Array.fromAsync(asyncGen())ES2026
Named regex groups/(?<y>\d{4})-(?<m>\d{2})/.exec(s).groups.yES2018

All of these run in Node.js 24 and in current Chrome, Edge, Firefox and Safari. Older browsers may need a polyfill, so check MDN’s compatibility table before you rely on one in public-facing code.

Browser DOM basics

SyntaxWhat it does
document.querySelector("#status")First element matching a CSS selector, or null
document.querySelectorAll(".row")All matches (a NodeList you can loop with for...of)
el.textContent = "OK"Set text safely. Avoid innerHTML with untrusted data
el.classList.toggle("hidden")Add or remove a class
el.dataset.idRead a data-id attribute
btn.addEventListener("click", e => { ... })Handle an event
document.createElement("li") · list.append(li)Create and insert an element
localStorage.setItem("k", JSON.stringify(v))Persist small values in the browser
new URL(location.href).searchParams.get("q")Read a query-string value

Node.js for server admins

SyntaxWhat it does
await readFile("app.log", "utf8") · await writeFile(p, data)Read or write a whole file (node:fs/promises)
await readdir(dir) · await stat(p) · await mkdir(p, { recursive: true })List, inspect and create
promisify(execFile)("df", ["-h", "/"])Run a command without a shell; resolves to { stdout, stderr }
process.argv.slice(2) · process.env.HOMEScript arguments · environment
os.loadavg() · os.freemem() · os.hostname()Basic host facts (node:os)
path.join("/var", "log", "x.log") · path.basename(p, ".log")Build and split paths
import.meta.dirnameDirectory of the current module (no __dirname in ES modules)
node --env-file=.env app.jsLoad environment variables from a file
node --watch app.jsRestart when files change
node --run buildRun a package.json script without npm

Count error lines in a large log without loading it into memory:

import { createReadStream } from "node:fs";
import { createInterface } from "node:readline";

const rl = createInterface({ input: createReadStream("/var/log/app.log"), crlfDelay: Infinity });
let errors = 0;
for await (const line of rl) {
  if (line.includes("ERROR")) errors++;
}
console.log(`errors: ${errors}`);

Use execFile or spawn with an argument array rather than exec with a built string. exec runs through a shell, so a hostname or file name containing ; or $() becomes a command.

Official documentation (checked 9 October 2026): MDN: JavaScript reference · ECMAScript Language Specification (TC39 draft) · MDN: Set · MDN: Iterator · Node.js v24 API documentation

JavaScript Cheat Sheet at a glance

JavaScript Cheat Sheet – short answer
In short: A compact reference for modern JavaScript (ES2024 and later) in the browser and Node.js, with the language examples run on Node.js 24.
JavaScript Cheat Sheet – what this guide covers
JavaScript Cheat Sheet: what this guide covers.

Related: TypeScript Cheat Sheet: Types, Generics and tsconfig · HTML Cheat Sheet: Elements, Attributes and Forms · CSS Cheat Sheet: Selectors, Flexbox, Grid and Modern CSS · Regex Tester for JavaScript.

Reading a lot of our guides? Go ad-free with srvScripts Pro for $6 a month. It also pays for new guides. Cancel any time.

Share this guide

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.