JAVASCRIPT • COLLECTIONS AND STRINGS

String Methods — Index and slice strings and use common string methods

Learn to access, extract, and transform text in JavaScript using built-in string methods.

Historical Context & Motivation

Almost every program you will ever write needs to deal with text. Whether it is a username typed into a login form, a tweet displayed on a social media feed, or a chat message in a multiplayer game, text data is everywhere. In programming, we store text inside objects called strings. But storing text is only half the battle — you also need tools to search through it, pull out pieces of it, and change it. That is exactly what string methods were designed to do.

The history of string manipulation stretches back to the earliest days of computing. Early programming languages treated text as raw arrays of numbers, which made even simple tasks like finding a word inside a sentence painfully complicated. Over decades, languages evolved to give programmers friendlier, more powerful ways to work with text. JavaScript, created in 1995, inherited many of these ideas and packaged them into a clean set of built-in string methods.

1963
ASCII Standard Published
The American Standard Code for Information Interchange (ASCII) assigns a number to each character, giving computers a shared way to represent text. This laid the groundwork for all string handling.
1972
C Language & Null-Terminated Strings
The C language stores strings as arrays of characters ending with a special null byte. Programmers must manually manage memory and write their own search and slice functions.
1995
JavaScript Is Born
Brendan Eich creates JavaScript in just 10 days. The language includes a built-in String object with methods like indexOf, charAt, and substring, making text manipulation far simpler for web developers.
2009–2015
ES5 & ES6 Enhancements
ECMAScript 5 adds trim(), and ECMAScript 6 (ES2015) introduces template literals, startsWith(), endsWith(), includes(), and repeat(), greatly expanding the string toolkit.

The key question this lesson tackles is: once you have a string, how do you pinpoint specific characters inside it, extract substrings from it, and transform it into exactly the form you need? JavaScript's string methods provide the answers.

Core Principles & Definitions

Before diving into individual methods, you need to understand a few foundational ideas about how JavaScript treats strings. These principles apply to every method you will learn in this lesson and beyond.

1

Strings Are Indexed

Each character in a string has a numeric position called an index. The first character is at index 0, not 1. The string "cat" has 'c' at index 0, 'a' at index 1, and 't' at index 2.
2

Strings Are Immutable

Once a string is created, its characters cannot be changed in place. Methods like toUpperCase() do not modify the original string — they return a new string. You must store the result in a variable if you want to keep it.
3

The .length Property

Every string has a length property that tells you how many characters it contains. For "Hello", .length returns 5. The last valid index is always length − 1.
4

Bracket Notation vs. charAt()

You can access a single character using str[i] (bracket notation) or str.charAt(i). Both return the character at index i. Bracket notation is more modern and widely used.
5

Methods Use Dot Syntax

String methods are called with a dot after the string value or variable: myStr.toUpperCase(). The dot tells JavaScript, "run this method on the string to its left." Arguments go inside the parentheses.
✦ KEY TAKEAWAY
Think of a string like a row of lockers in a school hallway. Each locker has a number on it (the index), starting from 0. You can peek into any locker to see the character inside, and you can copy characters from a range of lockers into a new row — but you can never repaint the letters already inside the original lockers. That is what immutability means: you always get a fresh copy.

Visual Explanation — String Indexing

The diagram below shows how the string "JavaScript" is laid out in memory. Each character sits in its own "cell" with a zero-based index number above it. Pay close attention to the fact that the last character, 't', is at index 9 even though the string has 10 characters. This off-by-one pattern is one of the most common sources of bugs for beginners.

The top row shows each character of "JavaScript" with its index above it. The cyan dashed box highlights the portion extracted by slice(4, 10), and the pink arrow marks the position returned by indexOf("S").

Notice the critical pattern with slice(start, end): the character at the start index is included, but the character at the end index is excluded. So slice(4, 10) grabs indices 4, 5, 6, 7, 8, and 9 — which spells "Script". This "up to but not including" convention is used throughout JavaScript and many other languages.

How Indexing & Slicing Work

Although strings are not math-heavy, understanding a few simple formulas helps you avoid off-by-one errors and use negative indices confidently. Let's define the key relationships.

LAST INDEX
lastIndex = str.length − 1
For "Hello" (length 5), the last index is 5 − 1 = 4. Attempting to access index 5 returns undefined.
SLICE LENGTH
characters extracted = end − start
slice(2, 7) extracts 7 − 2 = 5 characters. This formula works because the start index is included and the end index is excluded.
NEGATIVE INDEX CONVERSION
effectiveIndex = str.length + negativeIndex
When you pass a negative number to slice(), JavaScript converts it by adding the string's length. For a 10-character string, slice(-3) becomes slice(7), returning the last 3 characters.

These relationships show why zero-based indexing is so consistent. The formula end − start always tells you exactly how many characters you will get, with no need to add or subtract 1. This elegance is one of the reasons most programming languages start counting from 0.

💡 slice() vs. substring() vs. substr()
JavaScript has three methods that extract parts of a string. slice(start, end) is the most versatile because it supports negative indices. substring(start, end) works similarly but treats negative values as 0. substr(start, length) takes a start index and a character count, but it is considered deprecated. For new code, stick with slice().

Common String Methods — Detailed Breakdown

JavaScript provides dozens of string methods, but a core group handles the vast majority of real-world tasks. The table below organizes the most important ones into categories so you can quickly find the right tool for any job.

Essential JavaScript string methods grouped by purpose
MethodCategoryWhat It DoesExample
charAt(i)AccessReturns the character at index i"dog".charAt(1) → "o"
indexOf(sub)SearchReturns the first index where sub is found, or −1"banana".indexOf("na") → 2
lastIndexOf(sub)SearchReturns the last index where sub is found, or −1"banana".lastIndexOf("na") → 4
includes(sub)SearchReturns true if sub exists anywhere in the string"team".includes("ea") → true
startsWith(sub)SearchReturns true if the string begins with sub"hello".startsWith("he") → true
slice(start, end)ExtractExtracts from start up to (not including) end"abcdef".slice(1,4) → "bcd"
toUpperCase()TransformReturns a new string with all letters capitalized"hi".toUpperCase() → "HI"
toLowerCase()TransformReturns a new string with all letters lowercased"HI".toLowerCase() → "hi"
trim()TransformRemoves whitespace from both ends" ok ".trim() → "ok"
replace(old, new)TransformReplaces the first occurrence of old with new"aab".replace("a","x") → "xab"
replaceAll(old, new)TransformReplaces every occurrence of old with new"aab".replaceAll("a","x") → "xxb"
split(sep)ConvertSplits the string into an array of substrings"a-b-c".split("-") → ["a","b","c"]
repeat(n)GenerateReturns the string repeated n times"ha".repeat(3) → "hahaha"
This flowchart helps you choose the right method based on your goal: accessing a character, searching, extracting a substring, transforming text, or converting to an array.

When you are stuck deciding which method to use, ask yourself: "Am I looking for something, pulling something out, or changing something?" That question maps directly to the Search, Extract, and Transform categories in the diagram above.

Worked Example — Extracting a Domain from an Email

Let's walk through a realistic task: given an email address stored in a string, extract just the domain name (the part after the @ symbol) and convert it to lowercase. This combines several methods we have learned.

Extract the Domain from an Email Address
1
Step 1 — Define the input stringWe start with an email address stored in a variable. let email = "Student@SchoolMail.EDU"; Our goal is to extract "schoolmail.edu".
email = "Student@SchoolMail.EDU"
2
Step 2 — Find the position of the @ symbolWe use indexOf() to find where the @ sign appears. let atPos = email.indexOf("@"); The string is "Student@SchoolMail.EDU". Counting from 0, the @ is at index 7.
atPos = 7
3
Step 3 — Slice the domain portionWe want everything after the @, so we slice starting at atPos + 1 (index 8) to the end. When you omit the second argument, slice goes all the way to the end of the string. let domain = email.slice(atPos + 1);
domain = "SchoolMail.EDU"
4
Step 4 — Convert to lowercaseDomain names are case-insensitive, so we normalize to lowercase for consistency. domain = domain.toLowerCase(); Remember, toLowerCase() returns a new string — we must reassign it to domain.
domain = "schoolmail.edu"
5
Step 5 — Verify with includes()As a sanity check, we can verify the result contains ".edu": domain.includes(".edu") returns true. Our extraction and transformation worked perfectly.
true
⛓️ Chaining Methods
Because each method returns a new string, you can chain multiple calls on one line: email.slice(email.indexOf("@") + 1).toLowerCase(). This produces the same result as the multi-step approach but in a single expression. Chaining is concise, but make sure each step is clear before condensing your code.

Strengths & Limitations of String Methods

JavaScript's built-in string methods are powerful, but they have boundaries. Understanding what they handle well and where they fall short helps you choose the right approach and avoid frustration when a simple method is not enough.

Strengths vs. limitations of JavaScript string methods
StrengthLimitation
Built-in and require no extra libraries — available in every JS environmentreplace() only swaps the first match unless you use replaceAll() or a regex with the global flag
Immutability prevents accidental side effects — the original string is always safeImmutability means lots of new strings are created, which can slow down performance with very large text
slice() supports negative indices for counting from the end — very flexibleindexOf() is case-sensitive by default — searching for "hello" won't find "Hello" without extra steps
split() easily converts strings to arrays for looping and mappingComplex pattern matching (e.g., "find all phone numbers") requires regular expressions, not basic methods
Methods are chainable, enabling clean and readable one-line transformationsSome emoji and special Unicode characters count as 2 indices (surrogate pairs), which can break simple indexing
✦ KEY TAKEAWAY
Think of string methods as a Swiss Army knife — they handle a surprising range of everyday tasks with elegance. But just as you would not use a Swiss Army knife to cut down a tree, you should not expect indexOf() and replace() to handle complex patterns. For those jobs, you will eventually learn regular expressions — a more powerful (and more complex) tool.

Connection to Advanced String Handling

The string methods you have learned in this lesson form the foundation for more advanced text processing techniques. As you progress, you will encounter tools that extend what basic methods can do, particularly when dealing with pattern matching, internationalization, or large-scale data processing.

How today's methods connect to advanced text processing
Basic String Methods (This Lesson)Advanced Techniques (Future Topics)
indexOf() finds exact substringsRegular expressions match flexible patterns (e.g., any 3-digit number)
replace() swaps one fixed stringRegex with capture groups restructures text dynamically
toUpperCase() changes case for English letterstoLocaleUpperCase() handles language-specific casing rules (e.g., Turkish İ)
split() divides by a simple delimiterParsing libraries (like JSON.parse) handle complex structured text formats
Bracket notation accesses one character at a timeIterators and spread syntax ([...str]) handle multi-byte Unicode characters safely

As a next step, keep an eye out for template literals (backtick strings with ${} placeholders), which make it easy to embed variables and expressions directly inside strings. You will also encounter regular expressions, which work hand-in-hand with methods like match(), search(), and replace() to do pattern-based text processing. Mastering the basic methods first makes those advanced tools much easier to learn.

Practice Problems

PROBLEM 1 — CONCEPTUAL
Explain why "JavaScript"[10] returns undefined even though the string has 10 characters. What fundamental principle about string indexing does this illustrate?
PROBLEM 2 — BASIC CALCULATION
Given let word = "hamburger";, what does word.slice(3, 8) return? Show how you determine the answer using the index positions.
PROBLEM 3 — INTERMEDIATE
Write a JavaScript expression (one line) that takes the string " Hello, World! " and produces "hello, world!". You need to remove the whitespace from both ends and convert to lowercase.
PROBLEM 4 — APPLIED
A web app collects a file name from a user upload: let file = "Report_Final.PDF";. Write code that extracts just the file extension (without the dot) and converts it to lowercase. Your code should work for any file name, not just this one.
PROBLEM 5 — CRITICAL THINKING
Consider the string let msg = "abcabc";. The expression msg.indexOf("abc") returns 0, and msg.lastIndexOf("abc") returns 3. Without using replaceAll() or regular expressions, how could you replace every occurrence of "abc" with "XYZ" using only split() and join()? Explain why this technique works.

Lesson Summary

JavaScript strings are zero-indexed sequences of characters, where the first character is at position 0 and the last is at position length − 1. Strings are immutable, meaning every method returns a new string rather than modifying the original. You can access individual characters with bracket notation or charAt(), search for substrings with indexOf() and includes(), and extract portions with slice(start, end) where the start is included and the end is excluded.

Transformation methods like toUpperCase(), toLowerCase(), trim(), and replace() let you reshape text, while split() bridges the gap between strings and arrays. Because methods return new strings, you can chain them together for concise, readable transformations. These fundamental tools prepare you for more advanced text processing with regular expressions and template literals in future lessons.

Varsity Tutors • JavaScript • String Methods — Index and slice strings and use common string methods