JavaScript Strings

Strings are the most common data type you will work with. Learn template literals, the essential string methods, immutability, and patterns every JavaScript developer uses daily.

Beginner 10 min read 11 examples

String Basics

Strings can be written with single quotes, double quotes, or backticks. They are zero-indexed sequences of characters.

JavaScript
const a = 'single quotes';
const b = "double quotes";
const c = `backtick (template literal)`;

// Length
console.log("hello".length);  // 5

// Character access (zero-indexed)
const str = "JavaScript";
console.log(str[0]);          // "J"
console.log(str[4]);          // "S"
console.log(str.at(-1));      // "t" (last char - ES2022)
console.log(str.at(-2));      // "p"

// Escape sequences
const quote  = "She said \"hello\"";    // escaped double quote
const path   = 'C:\\Users\\Alice';       // escaped backslash
const newline = "Line 1\nLine 2";        // \n = newline
const tab    = "col1\tcol2";             // \t = tab

// String concatenation
const first = "John";
const last  = "Doe";
console.log(first + " " + last);   // "John Doe"
console.log(first.concat(" ", last)); // "John Doe"

Template Literals

Template literals (backticks) support interpolation, multiline strings, and tagged templates. Prefer them over concatenation.

JavaScript
const name = "Alice";
const age  = 30;

// Interpolation - any expression inside ${}
console.log(`Hello, ${name}!`);               // "Hello, Alice!"
console.log(`${name} is ${age} years old.`);  // "Alice is 30 years old."
console.log(`2 + 2 = ${2 + 2}`);              // "2 + 2 = 4"
console.log(`Upper: ${name.toUpperCase()}`);  // "Upper: ALICE"

// Ternary inside template
const isAdmin = true;
console.log(`Role: ${isAdmin ? "Admin" : "User"}`); // "Role: Admin"

// Multiline strings (preserves actual newlines)
const html = `
    <div class="card">
        <h2>${name}</h2>
        <p>Age: ${age}</p>
    </div>
`;

// Nested template literals
const items = ["apple", "banana", "cherry"];
const list = `Items: ${items.map(item => `[${item}]`).join(", ")}`;
console.log(list); // "Items: [apple], [banana], [cherry]"

Essential String Methods

The most commonly used methods for extracting and modifying substrings:

JavaScript
const str = "Hello, World!";

// slice(start, end) - preferred substring method
console.log(str.slice(7));       // "World!" (from index 7 to end)
console.log(str.slice(7, 12));   // "World" (index 7 up to, not including, 12)
console.log(str.slice(-6));      // "World!" (from 6th from end)
console.log(str.slice(-6, -1));  // "World"  (negative end)

// toUpperCase / toLowerCase
console.log(str.toUpperCase());  // "HELLO, WORLD!"
console.log(str.toLowerCase());  // "hello, world!"

// trim - remove leading/trailing whitespace
const padded = "   hello   ";
console.log(padded.trim());      // "hello"
console.log(padded.trimStart()); // "hello   "
console.log(padded.trimEnd());   // "   hello"

// repeat
console.log("ha".repeat(3));    // "hahaha"

// padStart / padEnd - pad to a minimum length
console.log("5".padStart(3, "0")); // "005" (useful for IDs, time formatting)
console.log("hi".padEnd(10, "."));  // "hi........"

Search and Test Methods

JavaScript
const text = "JavaScript is awesome and JavaScript is fun";

// includes - boolean check (preferred for existence check)
console.log(text.includes("awesome"));   // true
console.log(text.includes("python"));    // false
console.log(text.includes("Java", 15));  // true (search from index 15)

// startsWith / endsWith
console.log(text.startsWith("Java"));    // true
console.log(text.endsWith("fun"));       // true
console.log(text.startsWith("awesome", 14)); // true (from index 14)

// indexOf / lastIndexOf - return position or -1
console.log(text.indexOf("JavaScript"));     // 0 (first occurrence)
console.log(text.lastIndexOf("JavaScript")); // 26 (last occurrence)
console.log(text.indexOf("Python"));         // -1 (not found)

// search - like indexOf but accepts RegExp
console.log(text.search(/java/i));   // 0 (case-insensitive match)

// match - extract matches
const matches = text.match(/JavaScript/g); // global flag = all matches
console.log(matches); // ["JavaScript", "JavaScript"]

const dateStr = "2024-01-15";
const dateParts = dateStr.match(/(\d{4})-(\d{2})-(\d{2})/);
console.log(dateParts[1]); // "2024"
console.log(dateParts[2]); // "01"

Transform and Format

JavaScript
// replace - replaces first match
const str = "cats are great, cats are cute";
console.log(str.replace("cats", "dogs")); // "dogs are great, cats are cute"

// replaceAll - replaces all matches (ES2021)
console.log(str.replaceAll("cats", "dogs")); // "dogs are great, dogs are cute"

// replace with function
const result = "hello world".replace(/\b\w/g, char => char.toUpperCase());
console.log(result); // "Hello World" (title case)

// String.fromCharCode / charCodeAt
console.log("A".charCodeAt(0));      // 65
console.log(String.fromCharCode(65)); // "A"

// Number formatting with strings
const price = 1234567.89;
console.log(price.toFixed(2));             // "1234567.89"
console.log(price.toLocaleString("en-US")); // "1,234,567.89"

// at() method (ES2022) - cleaner than length-based access
const arr = "Hello";
console.log(arr.at(0));  // "H"
console.log(arr.at(-1)); // "o"

Split and Join

split() converts a string to an array. join() (on arrays) converts back. They are inverses of each other.

JavaScript
// split - string to array
const csv = "apple,banana,cherry";
const fruits = csv.split(",");
console.log(fruits); // ["apple", "banana", "cherry"]

const words = "hello world foo".split(" ");
console.log(words);  // ["hello", "world", "foo"]

const chars = "abc".split("");
console.log(chars);  // ["a", "b", "c"]

// split with limit
console.log("a,b,c,d".split(",", 2)); // ["a", "b"]

// join - array to string
console.log(fruits.join(" - "));  // "apple - banana - cherry"
console.log(fruits.join(""));     // "applebananacherry"
console.log(fruits.join());       // "apple,banana,cherry" (default comma)

// Common pattern: reverse a string
const reversed = "hello".split("").reverse().join("");
console.log(reversed); // "olleh"

// Practical: parse a URL path
const path = "/api/users/42";
const parts = path.split("/").filter(Boolean); // filter removes empty strings
console.log(parts); // ["api", "users", "42"]

String Immutability

Strings in JavaScript are immutable primitives. Every string method returns a new string. The original is never modified.

JavaScript
let greeting = "hello";

// Attempting to modify in place - silently does nothing
greeting[0] = "H";
console.log(greeting); // "hello" - unchanged!

// All methods return new strings
const upper = greeting.toUpperCase();
console.log(greeting); // "hello"   - original unchanged
console.log(upper);    // "HELLO"   - new string

// You must reassign if you want the changed value
greeting = greeting.toUpperCase();
console.log(greeting); // "HELLO"

// Chaining methods (each returns a new string)
const cleaned = "  Hello, World!  "
    .trim()
    .toLowerCase()
    .replace("hello", "hi");
console.log(cleaned); // "hi, world!"

Quick Reference Table

MethodWhat it doesReturns
str.lengthNumber of charactersnumber
str.at(i)Character at index (supports negative)string
str.slice(s, e)Extract substringstring
str.toUpperCase()Uppercase copystring
str.toLowerCase()Lowercase copystring
str.trim()Remove whitespace at both endsstring
str.includes(sub)Does string contain sub?boolean
str.startsWith(sub)Does string start with sub?boolean
str.endsWith(sub)Does string end with sub?boolean
str.indexOf(sub)First index of sub (-1 if absent)number
str.replace(a, b)Replace first match of a with bstring
str.replaceAll(a, b)Replace all matches of a with bstring
str.split(sep)Split into arrayarray
str.repeat(n)Repeat string n timesstring
str.padStart(n, p)Pad start to length n with pstring

Frequently Asked Questions

Yes. String methods never modify the original string - they always return a new one. str.toUpperCase() returns a new uppercase string; str itself is unchanged. This is why you must always capture the return value: const upper = str.toUpperCase(). Attempting to set a character directly (str[0] = "X") silently does nothing in non-strict mode.

Use slice(start, end) - it accepts negative indices (counting from end) and is the modern standard. substring(start, end) is similar but swaps arguments if start > end and does not support negative indices. substr(start, length) is deprecated - avoid it. Stick with slice() for all substring extraction.

Use str.includes(substring) which returns a boolean - it is the clearest option. For case-insensitive search: str.toLowerCase().includes(sub.toLowerCase()). For finding the index position use str.indexOf(sub) which returns -1 if not found. For pattern matching use a RegExp with str.test() or str.match().

Number to string: String(42), (42).toString(), or `${42}` (template literal). String to number: Number("42"), parseInt("42"), parseFloat("3.14"), or the unary plus +"42". parseInt also accepts a radix: parseInt("ff", 16) converts hex. Always prefer Number() for clean numeric strings.