Module 1 · Foundations & First Steps ⏱ 19 min

Strings & Their Methods

By the end of this lesson you will be able to:
  • Measure and inspect strings with length, indexing, and includes
  • Clean and normalise user input with trim, toLowerCase, and toUpperCase
  • Extract substrings with slice and understand the exclusive end index
  • Convert between strings and arrays with split and join

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
A string is an ordered sequence of characters. Index 0 is the first; length is the total count.

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
Measure, index, and search a string. Press Run.
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["&nbsp;&nbsp;Ada&nbsp;&nbsp;"] --> 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
A cleanup pipeline: trim removes edges, toLowerCase normalises case, then the string is ready to compare.
Clean up messy input before you compare or store it.
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
slice(0, 4) includes indexes 0-3; the end index is exclusive.
Extract pieces of a string without changing the original.
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.

Convert between strings and arrays, then reshape the text.
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(" | "));
Exercise

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 "."
}
Exercise

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());
Exercise

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);
Exercise

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;
}
Exercise

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
}

Recap

  • length counts characters; bracket notation reads by zero-based index.
  • includes searches case-sensitively; normalise case first for loose matching.
  • trim, toLowerCase, and toUpperCase clean and normalise input.
  • slice(start, end) extracts up to but not including the end index.
  • split breaks a string into an array; join glues 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.

Checkpoint quiz

What does "hello".length return?

What does "a-b-c".split("-") produce?

After const s = "hi"; s.toUpperCase();, what is the value of s?

Go deeper — technical resources