Regular expressions
A regular expression (regex) describes a pattern of text. Write it between slashes, /pattern/flags.
| Pattern | Matches |
|---|---|
. | any one character |
\d \w \s | a digit, a word character (letter/digit/_), a whitespace |
[abc] [a-z] [^0-9] | one of / a range / anything except |
* + ? {2,4} | 0 or more / 1 or more / optional / 2 to 4 times |
^ $ \b | start / end of text / word boundary |
(...) (?<name>...) a|b | a group / a named group / a or b |
regex.test(text)
Does the pattern match anywhere? Returns true or false.
console.log(/^\d{4}$/.test("2026"), /^\d{4}$/.test("20266"));
console.log(/hello/i.test("Say HELLO"));
const isEmail = (s) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s);
console.log(isEmail("sita@example.com"), isEmail("not-an-email"));
Output:
true false
true
true false
text.match(regex)
Without the g flag it returns the first match with its groups; with g it returns every match.
console.log("a1b22c333".match(/\d+/g));
const m = "Date: 2026-10-04".match(/(\d{4})-(\d{2})-(\d{2})/);
console.log(m[0], m[1], m[2], m[3]);
console.log("none".match(/\d/));
Output:
[ '1', '22', '333' ]
2026-10-04 2026 10 04
null
Named groups
Name the parts of a match and read them from groups.
const { year, month } = "2026-10-04".match(/(?<year>\d{4})-(?<month>\d{2})/).groups;
console.log(year, month);
Output:
2026 10
matchAll and exec
Every match with all of its details.
for (const m of "a=1, b=22".matchAll(/(\w)=(\d+)/g)) {
console.log(m[1], m[2], m.index);
}
Output:
a 1 0
b 22 5
replace with a regex
Replace patterns, with groups and functions.
console.log("2026-10-04".replace(/(\d+)-(\d+)-(\d+)/, "$3/$2/$1"));
console.log("a b c".replace(/\s+/g, " "));
console.log("snake_case_name".replace(/_(\w)/g, (_, c) => c.toUpperCase()));
Output:
04/10/2026
a b c
snakeCaseName
split with a regex
Split on a pattern.
console.log("a, b;c d".split(/[,;\s]+/));
Output:
[ 'a', 'b', 'c', 'd' ]
| Flag | Meaning |
|---|---|
g | global: find all matches |
i | ignore case |
m | ^ and $ match at each line |
s | dot also matches a newline |
u | full Unicode support |
Be careful with patterns like
(a+)+on long text: they can take forever ("catastrophic backtracking"). Keep patterns simple, and do not use regex to parse HTML.
The DOM: the page as objects
These need a web page (they are shown, not run here). Put your script after the HTML it uses, or use defer.
Selecting elements
querySelector returns the first match; querySelectorAll returns all of them.
const title = document.querySelector("h1");
const items = document.querySelectorAll(".item");
const byId = document.getElementById("menu");
items.forEach((el) => console.log(el.textContent));
const boxes = [...document.querySelectorAll("input[type=checkbox]")].filter((b) => b.checked);
Changing content, classes and styles
Use textContent for text (safe) rather than innerHTML for user input.
const box = document.querySelector("#box");
box.textContent = "Hello!";
box.classList.add("active");
box.classList.toggle("hidden");
box.style.backgroundColor = "gold";
box.setAttribute("title", "tooltip");
console.log(box.classList.contains("active"));
Creating and removing elements
Build elements in code and add them to the page.
const li = document.createElement("li");
li.textContent = "New item";
document.querySelector("ul").append(li);
li.remove();
Events
addEventListener runs your function when something happens. event.target is the element involved; preventDefault() stops the default action.
document.querySelector("form").addEventListener("submit", (event) => {
event.preventDefault();
const name = new FormData(event.target).get("name");
console.log("Hello", name);
});
// one listener for many items (event delegation)
document.querySelector("ul").addEventListener("click", (e) => {
if (e.target.matches("li")) e.target.classList.toggle("done");
});
Errors and modules
try / catch / finally and throw
Handle errors; throw your own. Errors have name and message.
function parseAge(text) {
const n = Number(text);
if (!Number.isInteger(n) || n < 0) throw new RangeError("invalid age: " + text);
return n;
}
try {
parseAge("-3");
} catch (e) {
console.log(e.name, "-", e.message);
} finally {
console.log("always runs");
}
class AppError extends Error {}
console.log(new AppError("x") instanceof Error);
Output:
RangeError - invalid age: -3
always runs
true
import and export (modules)
Split code across files. Shown, not run.
// math.js
export const add = (a, b) => a + b;
export default function square(n) { return n * n; }
// main.js
import square, { add } from "./math.js";
console.log(add(2, 3), square(4));
Optional chaining on calls, and labels worth knowing
Small features that make code safer: ?. on methods, ??= and ||= assignment.
const cfg = { retries: 0 };
cfg.retries ??= 3;
cfg.name ||= "default";
console.log(cfg);
console.log(cfg.run?.(), [1, 2, 3].at?.(-1));
Output:
{ retries: 0, name: 'default' }
undefined 3
Where to go next
- Apply these tools to classic problems in the JavaScript: 20 Interview Programs course.
- Read MDN Web Docs (developer.mozilla.org): the best reference for every method.
- Build small projects: a to-do list, a quiz, a weather app using
fetch.
You have finished the reference course. Keep it bookmarked: it is built to be searched and reused.

Comments
Loading comments…