# JavaScript Cheat Sheet: Modern Syntax for Browser and Node

Source: https://srvscripts.com/guides/javascript-cheat-sheet/
Updated: 2026-10-09
Publisher: srvScripts (https://srvscripts.com/)

**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

| Syntax | What it does | Result |
| --- | --- | --- |
| const host = "web01" | Block-scoped constant binding (the object it points to can still change) |  |
| let count = 0 | Block-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 array | true/false |
| 0 == "" · 0 === "" | Loose vs strict equality. Use === | true · false |
| cfg.port || 3306 | Fallback for any falsy value, including 0 and "" | 3306 if port is 0 |
| cfg.port ?? 3306 | Fallback only for null or undefined | 0 if port is 0 |
| cfg.nested?.deep | Optional chaining: undefined instead of a TypeError | undefined |
| x ??= 5 · x ||= "default" | Assign only if nullish · if falsy |  |
| Number("42px") · parseInt("42px", 10) | Strict vs lenient number parsing | NaN · 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 ** 64n | BigInt for integers above Number.MAX_SAFE_INTEGER | 18446744073709551616n |

## Strings and template literals

| Syntax | What 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

| Syntax | What 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

| Syntax | What 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

| Syntax | What 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

| Feature | Example | Since |
| --- | --- | --- |
| Group items by a key | Object.groupBy(rows, r => r.type) | ES2024 |
| Group into a Map | Map.groupBy(nums, n => n % 2 ? "odd" : "even") | ES2024 |
| Set operations | a.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 iterable | Iterator.from(arr).drop(1).toArray() | ES2025 |
| Escape text for a regex | new RegExp(RegExp.escape("1.2.3.4")) | ES2025 |
| Run sync or async code as a promise | Promise.try(() => mayThrow()) | ES2025 |
| Collect an async iterable | await Array.fromAsync(asyncGen()) | ES2026 |
| Named regex groups | /(?\d{4})-(?\d{2})/.exec(s).groups.y | ES2018 |

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

| Syntax | What 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.id | Read 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

| Syntax | What 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.HOME | Script 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.dirname | Directory of the current module (no __dirname in ES modules) |
| node --env-file=.env app.js | Load environment variables from a file |
| node --watch app.js | Restart when files change |
| node --run build | Run 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference) · [ECMAScript Language Specification (TC39 draft)](https://tc39.es/ecma262/) · [MDN: Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) · [MDN: Iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator) · [Node.js v24 API documentation](https://nodejs.org/docs/latest-v24.x/api/)

## JavaScript Cheat Sheet at a glance

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.

**Related:** [TypeScript Cheat Sheet: Types, Generics and tsconfig](https://srvscripts.com/guides/typescript-cheat-sheet/) · [HTML Cheat Sheet: Elements, Attributes and Forms](https://srvscripts.com/guides/html-cheat-sheet/) · [CSS Cheat Sheet: Selectors, Flexbox, Grid and Modern CSS](https://srvscripts.com/guides/css-cheat-sheet/) · [Regex Tester for JavaScript](https://srvscripts.com/tools/regex-tester/).
