Learn

Learn

JavaScript Strings — The Basics

Build a real mental model of JavaScript strings: why they're immutable, how indexing and length work, template literals, and how searching, slicing and transforming all return new strings.

XCODXLearn · Updated

Introduction

A string is a sequence of characters — text held in a single value. Anything you type, display, or read from a user is a string: a name, a URL, a line from a file, the contents of an input box. You write one with quotes, and JavaScript treats single quotes, double quotes and backticks as three ways to spell the same kind of value.

Why does text need its own type, distinct from numbers? Because the operations differ completely: you don't add two names, you *join* them; you don't halve a sentence, you *slice* it. A dedicated string type gives you a vocabulary — length, indexing, search, slice, replace, split — for working with text as a first-class thing rather than a bag of characters.

The one idea that makes everything else fall into place is immutability: a JavaScript string can never be changed once created. Every method that looks like it edits a string actually returns a brand-new one. Hold onto that and the rest of this guide — indexing, length, template literals, searching and slicing — is just detail hung on that frame.

const single = 'hello';
const double = "hello";
const backtick = `hello`;   // a template literal — more on these below

Lessons

1. Strings are immutable

This is the foundation. A string is immutable: none of its characters can be reassigned, and no method changes it in place. toUpperCase(), replace(), slice() — every one of them leaves the original untouched and hands you a *new* string. If you want the result, you must capture the return value; calling a string method and ignoring what it returns does nothing at all.

let greeting = 'hello';
greeting.toUpperCase();        // returns 'HELLO' — but we ignored it
console.log(greeting);         // 'hello' — unchanged

greeting = greeting.toUpperCase(); // capture the new string
console.log(greeting);         // 'HELLO'

Because strings are immutable, you never worry about one part of your program changing a string another part is holding — a common source of bugs with mutable values like arrays. The trade-off is that you must *reassign* to keep a transformed result.

2. Length and indexing

A string knows its size through length, and you reach any character by its index, counting from 0 — exactly like an array. The last character sits at index length - 1, or more readably at at(-1). Reading past the end returns undefined rather than throwing.

const word = 'JavaScript';

word.length;      // 10
word[0];          // 'J'   (first character)
word.at(-1);      // 't'   (last character)
word[99];         // undefined — no error for a missing index

3. Building strings: concatenation and template literals

You can join strings with +, but the modern and far more readable way is a template literal — a string in backticks where ${...} drops a value straight into the text. Template literals also span multiple lines without escape characters, which makes building messages, HTML or SQL far cleaner than gluing pieces together with +.

const name = 'Ada';
const age = 36;

const plus = 'Hi ' + name + ', age ' + age;     // old way
const tmpl = `Hi ${name}, age ${age}`;           // template literal

console.log(tmpl);   // 'Hi Ada, age 36'

4. Searching inside a string

To ask whether a string contains something, reach for includes() — it returns a plain true or false. When you need the position, indexOf() returns the index of the first match or -1 if there is none, and startsWith() / endsWith() answer the common edge cases directly. These are the everyday tools for validation and matching.

const url = 'https://xcodx.io/editor';

url.includes('xcodx');     // true
url.startsWith('https');   // true
url.indexOf('/editor');    // 15  (-1 if not present)

5. Taking a piece with slice

To copy a run of characters into a new string, use slice(start, end). Like array slicing it is half-open — it includes start and excludes end — and it accepts negative indices to count from the end. Because a string is immutable, slice() can only ever return a new string; the original is never touched.

const s = 'JavaScript';

s.slice(0, 4);    // 'Java'   (index 0 up to, not including, 4)
s.slice(4);       // 'Script' (to the end)
s.slice(-6);      // 'Script' (last six characters)

6. Transforming: case, whitespace, replace and split

The remaining everyday operations all follow the same immutable pattern — each returns a new string. toUpperCase() / toLowerCase() change case; trim() removes surrounding whitespace (invaluable for cleaning user input); replace() swaps text; and split() breaks a string into an array of pieces around a separator. Two of these are big enough to have their own reference pages.

  • replace() — swap the first match (or, with a global regex, every match) for new text.
  • split() — break a string into an array, e.g. a CSV line into fields.
  • trim(), toUpperCase(), padStart() and friends — small, single-purpose transforms you'll reach for constantly.

That's the whole model. A string is an immutable sequence of characters; length and 0-based indexing reach into it; template literals build it; includes/indexOf search it; slice copies a piece of it; and the transforming methods each hand back a *new* string. Everything else is a specific method resting on those ideas.

Practice

Check your model. Given let s = 'hello', what does s.toUpperCase() on its own line leave in s? (Answer: 'hello' — the method returns 'HELLO' but strings are immutable, so s is unchanged unless you reassign it.)

Now experiment for real — build a greeting with a template literal, then slice and upper-case a piece, and confirm the original survives every step:

Next steps

You have the mental model — now put it to work. Browse runnable JavaScript string examples for copy-paste snippets, follow how to reverse a string for a classic task, or read the focused references for replace() and split(). If arrays are next on your list, start with JavaScript arrays — the basics. Every snippet runs in the online JavaScript compiler or the full editor.

Frequently asked questions

Are JavaScript strings mutable?
No. Strings are immutable — you cannot change a character in place, and every string method returns a new string rather than modifying the original. Reassign the variable to keep a transformed result.
How do I get the last character of a string?
Use str[str.length - 1], or the more readable str.at(-1). The last index is length - 1 because indexing starts at 0.
What's the difference between single quotes, double quotes and backticks?
Single and double quotes are interchangeable for plain strings. Backticks create a template literal, which supports ${expression} interpolation and multi-line text.
How do I check whether a string contains another string?
Use str.includes('text') for a true/false answer, or str.indexOf('text') when you need the position (it returns -1 if not found).