String Methods

Learn the core built-in string methods for inspecting, searching, extracting, and transforming text, and understand how template literals simplify building strings.

Strings are one of the most common data types you will work with — page text, form input, API responses, and URLs are all strings. JavaScript gives strings a rich set of built-in methods for reading and reshaping text without writing manual character-by-character loops.

Strings are immutable

Every string method you call returns a brand-new string; none of them change the original string in place. Strings in JavaScript are immutable primitive values, so str.toUpperCase() does not modify str — it hands back a new, uppercase string that you must capture, usually by reassigning it or storing it in a new variable.

This trips up beginners constantly: calling name.trim() on its own line does nothing observable. You need name = name.trim(); (or use the result directly) for the change to matter.

Reading and searching a string

length is a property (not a method — no parentheses) that tells you how many UTF-16 code units are in a string, which for most text matches the number of characters you see.

Several methods answer yes/no or position questions about text without extracting anything: includes() checks whether a substring appears anywhere, startsWith() and endsWith() check the two ends, and indexOf() returns the numeric position of the first match (or -1 if it isn't found).

• str.length — number of characters in the string • str.includes(sub) — true if sub appears anywhere in str • str.startsWith(sub) / str.endsWith(sub) — true if str begins/ends with sub • str.indexOf(sub) — index of the first occurrence, or -1 if not found

Extracting pieces of a string

slice(start, end) and substring(start, end) both pull out a portion of a string between two indexes (the character at end is not included), but they behave differently with negative numbers: slice(-4) counts from the end of the string, while substring treats negative arguments as 0. In practice, prefer slice() — it is more predictable and works for both strings and arrays.

split(separator) breaks a string into an array of substrings wherever the separator occurs — for example "a,b,c".split(",") produces ["a", "b", "c"]. It is the opposite of Array.prototype.join(), which glues an array back into a string.

Transforming a string

replace(search, replacement) swaps out the first match of search with replacement; replaceAll(search, replacement) swaps out every match. search can be a plain string or a regular expression (with replace, a global regex /x/g also replaces every match).

trim() removes whitespace from both ends of a string (handy for cleaning up form input); trimStart() and trimEnd() trim only one side. padStart(targetLength, padString) and padEnd(targetLength, padString) pad a string up to a target length, which is often used to zero-pad numbers like "7".padStart(2, "0") → "07".

Template literals

Template literals use backticks (` `) instead of quotes and let you embed expressions directly inside a string using ${...}, which is far more readable than string concatenation with +. They also support real multi-line strings without needing \n` escapes or concatenation.

Template literals do not replace the string methods above — you can still call .trim(), .slice(), and so on, on the result of a template literal, since it produces an ordinary string.

Common string method calls

String methods never mutate the original string — always use or store the returned value. ${...} inside a template literal can hold any expression, not just a variable name. Method calls can be chained, e.g. str.trim().toLowerCase().

const s = "  Hello, SampleApp!  ";

s.length;                          // 21
s.trim();                          // "Hello, SampleApp!"
s.includes("App");                 // true
s.indexOf("Hello");                // 2
s.slice(2, 7);                     // "Hello"
s.replace("Hello", "Hi");          // "  Hi, SampleApp!  "
s.trim().split(", ");              // ["Hello", "SampleApp!"]

const name = "Ana";
const greeting = `Hi, ${name}! You have ${3 + 2} new messages.`;

Code Examples

Chains trim() to remove stray whitespace and toLowerCase() to normalize casing, a common cleanup step before comparing or storing user-entered email addresses. Expected result: jane.doe@example.com email.trim().toLowerCase() — each method returns a new string, so the next method runs on that result.

Splits a full name into words, takes the first character of each word, uppercases it, and joins the letters back together — a realistic pipeline combining several string and array methods. Expected result: GH AL part[0] reads the first character of a string using array-style indexing, which works because strings are indexable like read-only arrays of characters.

fullName.trim().split(" ") first cleans stray spaces, then breaks the name into an array of words.

slice(-4) grabs the last four characters regardless of how long the input string is, a common pattern for masking sensitive data. padStart demonstrates zero-padding an ID number for consistent display. Expected result: ** ** 1234 00042 cardNumber.slice(-4) — a negative start index counts backward from the end of the string.

Common mistake: Using substring(-4) instead of slice(-4) here would not work as expected, because substring() clamps negative arguments to 0 and would return the entire string.

const email = "  JANE.DOE@Example.com  ";

const cleaned = email.trim().toLowerCase();
console.log(cleaned);
function initials(fullName) {
  return fullName
    .trim()
    .split(" ")
    .map(part => part[0].toUpperCase())
    .join("");
}

console.log(initials("grace hopper"));
console.log(initials("  ada lovelace "));
function maskCard(cardNumber) {
  const last4 = cardNumber.slice(-4);
  return "**** **** **** " + last4;
}

console.log(maskCard("4111111111111234"));

function formatId(n) {
  return String(n).padStart(5, "0");
}
console.log(formatId(42));

Important Rules

String methods always return a new string; the original string is never modified.

indexOf() returns -1 (not null or undefined) when nothing is found — always compare with === -1, never treat it as falsy on its own since a match at index 0 is falsy-looking but valid.

Prefer slice() over substring() for extracting substrings, especially when negative indexes are involved.

Template literals (backticks) are for building strings with embedded expressions or multiple lines; regular quotes are fine for simple fixed text.

Where this shows up

String cleanup and formatting is everywhere: trimming and lowercasing emails before saving them, validating usernames with startsWith/endsWith, splitting comma-separated values from a CSV file or API response, masking sensitive data like card numbers, and building dynamic UI text with template literals instead of clunky string concatenation.

str.trim(); console.log(str); // still has whitespace str = str.trim(); console.log(str); // whitespace removed

Calling a string method does nothing on its own — it produces a new string that must be captured (reassigned or used directly), because strings cannot be changed in place.

if (str.indexOf("x")) { /* found */ } if (str.indexOf("x") !== -1) { /* found */ } indexOf("x") returns 0 when the match is at the very start of the string, and 0 is falsy in JavaScript, so a plain truthy check silently fails for matches at position 0. Compare explicitly against -1, or use includes() instead.

[Multiple Choice] What does "Hello".slice(1, 3) return? A. "He" B. "el" C. "ell" D. "llo"

B. "el" — slice(1, 3) starts at index 1 ('e') and stops before index 3 ('l' at index 3 is excluded), returning "el" (characters at indexes 1 and 2).

[True / False] Calling myString.toUpperCase() changes myString itself to be uppercase. A. True B. False

B. False — False. Strings are immutable in JavaScript, so toUpperCase() returns a new uppercase string; myString is unchanged unless you reassign it, e.g. myString = myString.toUpperCase().

Write a function slugify(title) that converts a string like " My First Blog Post! " into a URL-friendly slug like "my-first-blog-post" — trim whitespace, lowercase everything, and replace each space with a hyphen. (You don't need to remove punctuation for this exercise.) function slugify(title) { return title.trim().toLowerCase().replaceAll(" ", "-"); } console.log(slugify(" My First Blog Post! ")); // "my-first-blog-post!"

Chain trim(), toLowerCase(), and then use replaceAll(" ", "-") or split(" ").join("-").