Almost every program handles text: usernames, search queries, addresses, CSV exports. Raw text from a user is messy — extra spaces, mixed case, typos in punctuation. If you try to compare "Ada" with " ada " using ===, they look like two different people.
String methods are your cleanup crew. They let you measure text, search inside it, change case, remove padding, and reshape it. All of them share one rule: strings are immutable. A method never changes the original string; it always returns a new one. Forget that rule and you'll stare at a bug where your "fixed" string is still broken.
flowchart LR S["#quot;Hello#quot;"] --> I0["H<br/>index 0"] S --> I1["e<br/>index 1"] S --> I2["l<br/>index 2"] S --> I3["l<br/>index 3"] S --> I4["o<br/>index 4"] S --> L["length = 5"] style S fill:#e0900b,color:#fff style L fill:#3776ab,color:#fff
Measuring and inspecting
The most basic inspection is length, which counts characters. Reach a single character with bracket notation — greeting[0] — just like an array. Strings are zero-indexed, so index 0 is the first character and index length - 1 is the last.
Test whether a substring exists with includes. It is case-sensitive: "Hello".includes("h") is false because the H is uppercase. That single detail causes more search bugs than anything else in beginner code.
const greeting = "Hello, Ada";
console.log(greeting.length); // 10
console.log(greeting[0]); // "H"
console.log(greeting.includes("Ada")); // true
console.log(greeting.includes("ada")); // false — case matters
const id = "user_42";
console.log(id.length);
console.log(id[0], id[id.length - 1]);
console.log(id.includes("42"));
console.log(id.includes("user"));
console.log("Case sensitive:", "Yes".includes("yes"));
Cleaning input: trim and case
User input arrives with surprises: leading spaces from a copy-paste, trailing tabs from a form field, or inconsistent capitalization from a phone keyboard. The fix is a small pipeline.
trim() removes whitespace from both ends. toLowerCase() and toUpperCase() return new strings in the chosen case. Chain them together when you need both: name.trim().toLowerCase() first strips the padding, then lowercases the result.
Because strings are immutable, the order matters and you must capture the return value. name.trim() on its own does nothing useful unless you store the result.
flowchart LR R[" Ada "] --> T["trim()"] T --> L["toLowerCase()"] L --> C["#quot;ada#quot;<br/>ready to compare"] style T fill:#e0900b,color:#fff style L fill:#e0900b,color:#fff style C fill:#1e7f3d,color:#fff
const raw = " Ada Lovelace ";
const clean = raw.trim().toLowerCase();
console.log(clean);
const code = "js";
console.log(code.toUpperCase());
console.log("Original unchanged:", raw);
Slicing and extracting
slice(start, end) returns the characters from start up to but not including end. That "exclusive end" rule is the classic off-by-one trap. slice(0, 4) gives characters at indexes 0, 1, 2, and 3 — four characters total.
Omit the end and slice runs to the end of the string. Negative indexes count from the back, though for now just remember the two-argument form.
const word = "JavaScript";
word.slice(0, 4); // "Java" — indexes 0,1,2,3
word.slice(4); // "Script" — from index 4 to the end
flowchart LR S["JavaScript"] --> Z["J a v a S c r i p t"] Z --> SL1["slice(0,4)<br/>indexes 0 1 2 3<br/>Java"] Z --> SL2["slice(4)<br/>indexes 4 to 9<br/>Script"] style SL1 fill:#e0900b,color:#fff style SL2 fill:#3776ab,color:#fff
const lang = "JavaScript";
console.log(lang.slice(0, 4));
console.log(lang.slice(4));
console.log(lang.slice(2, 6));
console.log("Original:", lang);
Split and join: the string-array bridge
split(delimiter) breaks a string into an array of pieces. join(delimiter) glues an array back into a string. Together they let you convert between formats: a comma-separated list becomes an array, gets filtered or mapped, then becomes a pipe-separated list.
const csv = "js,html,css";
const list = csv.split(""); // ["js","html","css"]
list.join(" | "); // "js | html | css"
This pair is especially powerful with method chaining. You can split, process, and join in a single expression, which is how many text-transform pipelines are built.
const path = "docs/api/users";
const parts = path.split("/");
console.log(parts);
console.log(parts.join(" > "));
const tags = "red,green,blue";
console.log(tags.split(",").join(" | "));
Write initials(name) that returns the uppercase initials, each followed by a period. Example: initials("Ada Lovelace") returns "A.L.". A single name like "Madonna" returns "M.".
function initials(name) {
// return the uppercase initials, each followed by "."
}
Split the name on spaces with split(" ").
Take the first character of each part, uppercase it, join with ".", then add a final ".".
function initials(name) {
const parts = name.trim().split(" ");
const first = parts.map((p) => p[0].toUpperCase());
return first.join(".") + ".";
}
What does this print? A CSV string is split into an array, then joined with a separator.
const csv = "red,green,blue";
const list = csv.split(",");
console.log(list);
console.log(list.join(" | "));
console.log("Hello World".toUpperCase());
split(",") gives an array of three color strings.
join(" | ") puts " | " between them; toUpperCase capitalizes everything.
What does this print? Watch the exclusive end index and the unchanged original string.
const word = "JavaScript"; console.log(word.slice(0, 4)); console.log(word.slice(4)); console.log(word);
slice(0, 4) includes indexes 0, 1, 2, and 3 — four characters.
The original string is never modified by slice.
This function is meant to normalise a username to lowercase with no surrounding spaces, but it returns the original string unchanged. Fix it by using the return values of the string methods.
function cleanName(name) {
name.trim();
name.toLowerCase();
return name;
}
trim() and toLowerCase() return new strings; they do not modify the original.
Chain them and return the result: return name.trim().toLowerCase();
function cleanName(name) {
return name.trim().toLowerCase();
}
Write slugify(title) that turns a blog post title into a URL-friendly slug: trim surrounding spaces, convert to lowercase, and replace spaces with hyphens. Example: slugify(" Hello World ") returns "hello-world".
function slugify(title) {
// return a lowercase, trimmed, hyphenated slug
}
Trim first, then lowercase, then split on spaces and join with hyphens.
Chain the methods: title.trim().toLowerCase().split(" ").join("-").
function slugify(title) {
return title.trim().toLowerCase().split(" ").join("-");
}
Recap
lengthcounts characters; bracket notation reads by zero-based index.includessearches case-sensitively; normalise case first for loose matching.trim,toLowerCase, andtoUpperCaseclean and normalise input.slice(start, end)extracts up to but not including the end index.splitbreaks a string into an array;joinglues an array back into a string.- Strings are immutable: every method returns a new string; assign the result.
Next you'll use these tools to parse and transform more complex text, building small utilities that prepare raw data for storage and display.