Strings, Templates and Text
Strings are immutable
Quoting and escaping
Write strings in single quotes, double quotes or backticks — pick one style and keep it. To put a quote inside a like quote, escape it with a backslash:
const single = 'She said "hi"'; // mixed quotes need no escaping
const escaped = "She said \"hi\""; // same string, escaped
const template = `She said "hi"`; // backticks: the modern default (below)
Methods return new strings
let name = "ada";
name.toUpperCase(); // produces "ADA"...
console.log(name); // "ada" — the original is UNCHANGED
name = name.toUpperCase(); // ...so you store the result back
console.log(name); // "ADA"
If you get this instead: the original text — you called a method and dropped the result. Strings cannot be modified; every string method is a factory for a new string.
The everyday methods
Measure, search, cut, clean
const file = "report-2026.pdf";
console.log(file.length); // 13 — characters (careful: see Unicode below)
console.log(file.includes("2026")); // true
console.log(file.startsWith("re")); // true
console.log(file.slice(7, 11)); // "2026" — start included, end excluded
console.log(file.slice(-4)); // ".pdf" — negative counts from the end
console.log(" hi ".trim()); // "hi"
console.log("a,b,c".split(",")); // [ 'a', 'b', 'c' ] — an array now
console.log("7".padStart(3, "0")); // "007" — fixed-width numbers
replace and replaceAll
console.log("2026-05-01".replaceAll("-", "/")); // "2026/05/01"
console.log("aaa".replace("a", "b")); // "baa" — replace changes ONE
Template literals
Interpolation: values inside text
Backtick strings embed any expression with ${...} — no more quote-juggling
arithmetic:
const user = "Ada";
const score = 98;
console.log(`${user} scored ${score}% (${score >= 90 ? "pass" : "retry"})`);
// -> Ada scored 98% (pass)
Anything inside ${} is a full expression: arithmetic, comparisons, function calls.
Multi-line text comes free — press Enter inside a backtick string and the newline belongs to
the string.
Characters: code units versus code points
The emoji contraexample
const thumbs = "👍";
console.log(thumbs.length); // 2 (!) — stored as TWO UTF-16 code units
console.log(thumbs[0]); // half an emoji — a garbage character
console.log([...thumbs].length); // 1 — spread iterates real characters
Strings are sequences of UTF-16 code units, and characters outside the basic range (emoji,
rare scripts) take two units; indexing with [0] cuts them in half. The rule:
iterate with for...of or [...str] when real characters
matter — use length for storage size, never for "how many letters".
Numbers to text and back
Converting at the edges
console.log(String(42)); // "42"
console.log(Number("42.5")); // 42.5 — strict; garbage in, NaN out
console.log((1234.567).toFixed(2)); // "1234.57" — NOTE: a string comes back
console.log(Number("42px")); // NaN — Number refuses partial reads
Convert with Number()/String() — explicit and strict. Beware
toFixed: it formats (returns a string), it does not round the number in
place.
Intl: formatting for humans
console.log(new Intl.NumberFormat("de-DE").format(1234.5)); // 1.234,5
console.log(new Date().toLocaleDateString("en-GB")); // locale date
Never hand-format currencies and dates — the built-in Intl knows every locale's
rules.
A taste of regex
console.log(/2026/.test(file)); // true — "does the pattern appear?"
console.log(file.match(/\d{4}/)[0]); // "2026" — the first four digits
Regular expressions match patterns. Two methods cover day one: .test()
(boolean) and .match() (what was found). Reach for plain string methods first;
regex is for patterns, not for homework.
Practice: the string lab
The task
Run foundations/11_strings_lab.js with node, predicting each line.
Then build one line of "form output" yourself: trim a fake input, produce
Hello, Ada! with a template literal, and extract a filename's extension with
slice(-4).
The checklist
- You can explain why a method call alone never changed
name. - You reach for template literals instead of
+for sentences. - You know what
"👍".lengthreturns and the safe way to count characters. - You know
toFixedreturns a string, andNumber()refuses partial reads.