The same thinking, applied to text
Lesson 7-1 covered the method that keeps only the items passing a test and may hand back a shorter array: filter. Its neighbours divide the work up neatly, with map transforming one for one and reduce folding everything down to a single value.
This lesson moves that style of thinking to strings, and the most important habit carries over intact. String methods return new values instead of changing the original, so the result has to be captured or it is lost.
The everyday string toolkit
A surprising share of real engineering is text handling: cleaning form input, splitting CSV lines, matching search terms, and building URLs and file paths. These are the methods that do that work, and you will type them daily.
Most string methods match Python, renamed in camelCase, which is JavaScript's convention of gluing words together with capital letters as in toUpperCase:
| Job | Python | JavaScript |
|---|---|---|
| uppercase / lowercase | s.upper() / s.lower() | s.toUpperCase() / s.toLowerCase() |
| strip surrounding spaces | s.strip() | s.trim() |
| contains | "x" in s | s.includes("x") |
| starts / ends | s.startswith / s.endswith | s.startsWith / s.endsWith |
| slice a piece | s[0:3] | s.slice(0, 3) |
| split into array | s.split(",") | s.split(",") |
| join array into string | ",".join(xs) | xs.join(",") |
| replace | s.replace(a, b) | s.replaceAll(a, b) |
Two rows deserve a second look. JavaScript has no s[0:3] slicing syntax at all, only the slice method. And join switches sides: Python calls it on the separator, while JavaScript calls it on the array and passes the separator in.
Strings are immutable, exactly as in Python. Every method returns a new string and leaves the original untouched, which is why the results have to be assigned somewhere to be useful.
Cleaning, querying, and splitting one string
Six method calls covering the three families: one that cleans, three that answer questions or take pieces, and a pair that convert between a string and an array.
const raw = " Ada Lovelace "; const name = raw.trim(); console.log(name.toUpperCase()); console.log(name.includes("Love")); console.log(name.slice(0, 3)); const csv = "red,green,blue"; const parts = csv.split(","); console.log(parts.length); console.log(parts.join(" | "));
Output
ADA LOVELACE true Ada 3 red | green | blue
raw.trim() removes only the spaces at the two ends, leaving the space between the names alone, and its result is stored in name so the later calls work on the clean version.
The split and join pair is the one to remember, because it is how text becomes data and data becomes text. csv.split(",") produces the three-item array ['red', 'green', 'blue'], which is why .length reports 3, and parts.join(" | ") glues those items back into one string with the separator between each pair.
Normalizing an email address
Cleaning user input almost always means the same two steps, trimming stray spaces and lowercasing, since neither should change who the address belongs to.
const input = " USER@Example.COM "; const email = input.trim().toLowerCase(); console.log(email); console.log(email.endsWith(".com"));
Output
user@example.com
trueThe first line chains two methods, and chaining works here for the same reason it worked with map and filter: input.trim() returns a string, and a string has a .toLowerCase() method. Evaluation runs left to right, so the trimming happens first and the lowercasing acts on its result.
The order also matters for the check below. Lowercasing before calling endsWith(".com") is what makes the test succeed, because the original input ended in .COM and endsWith compares characters exactly, capital letters included.
Building initials from a full name
This one line combines the string toolkit with the array toolkit from unit 7, which is the real payoff of learning both.
const fullName = "grace brewster hopper"; const initials = fullName.split(" ").map(w => w[0].toUpperCase()).join("."); console.log(initials);
Output
G.B.H
Reading it as three stages makes it clear. split(" ") turns the sentence into ['grace', 'brewster', 'hopper']. map(w => w[0].toUpperCase()) replaces each word with one capital letter, giving ['G', 'B', 'H']. And join(".") puts the separator between them to produce G.B.H.
The arrow relies on strings being indexable like arrays, so w[0] is the first character of the word. That is a rare case where square brackets do work on a string, and note that only reading works this way, since assigning to w[0] would silently do nothing on an immutable string.
A result that was thrown away
Given const s = "hi"; followed by s.toUpperCase();, printing s still shows hi, because the new uppercase string was never stored anywhere.
toUpperCase builds and returns a brand new string, and a returned value that nothing catches is simply discarded. The original s cannot have changed, both because strings are immutable and because it was declared const.
Keeping the result means assigning it: const loud = s.toUpperCase();, after which loud holds "HI" and s still holds "hi". This is the single most common mistake with string methods, and it comes with no error message at all, so the symptom is always the same, a value that stubbornly refuses to change.
The same rule explains why
xs.map(...)on its own does nothing useful. Any method that returns a new value has to be assigned, chained, or passed onward. Only the mutating array methods from lesson 4-2, such aspushandsort, work by changing the thing they are called on.