JavaScript Strings

Master string immutability, character indexing with at(), template literals, slice vs substring, search methods, and modern text transformations.

1. What is a String?

A string is just text wrapped in quotes (like 'hello' or "world"). You use strings to store names, messages, URLs, or any piece of written information.

💡 Strings are Read-Only (Immutable)

In JavaScript, strings are read-only. You can read any character by its index, but you cannot change an individual letter directly with str[0] = "J". When you use methods like .toUpperCase(), JavaScript always creates and gives you a brand new string.

let tech = "react";

// ❌ In-place mutation has no effect
tech[0] = "R";
console.log(tech); // "react" (unchanged!)

// ✅ Create a new string by calling methods or reassigning
tech = tech.toUpperCase();
console.log(tech); // "REACT"
Output
react
REACT

2. Accessing Characters: `[]` vs `charAt()` vs `at()`

JavaScript provides three primary ways to access individual characters by their zero-based index:

Bracket Notation `str[i]` & `charAt()`

Traditional character access from index 0 up to length - 1.

  • str[99] out-of-bounds returns undefined
  • str.charAt(99) out-of-bounds returns ""
  • Cannot accept negative indices easily
const name = "Node";
console.log(name[0]);        // "N"
console.log(name.charAt(1)); // "o"
console.log(name[99]);       // undefined

Modern `str.at()` (ES2022 ✅)

Clean relative indexing that natively supports negative numbers from the end.

  • .at(-1) retrieves the last character
  • .at(-2) retrieves the second to last
  • No more verbose str[str.length - 1]
const name = "Node";
console.log(name.at(0));  // "N"
console.log(name.at(-1)); // "e" (last char)
console.log(name.at(-2)); // "d"

3. Template Literals & Interpolation

Enclosed by backticks (` `), template literals solve multiline string concatenation and dynamic expression embedding:

const product = "MacBook Pro";
const price = 1999;
const tax = 0.08;

// 1. Multiline & Expression Interpolation
const invoice = `Order Details:
- Product: ${product}
- Subtotal: $${price}
- Total: $${(price * (1 + tax)).toFixed(2)}`;

console.log(invoice);
Output
Order Details:
- Product: MacBook Pro
- Subtotal: $1999
- Total: $2158.92

4. Extracting Substrings: `slice()` vs `substring()`

While both extract portions of a string without modifying the original, their handling of negative indices and argument ordering differs:

`str.slice(start, end)` (Recommended ✅)

Extracts up to, but not including, index end.

  • Supports negative indices (counts from end)
  • Does not swap start and end
  • Matches Array.prototype.slice
const text = "JavaScript";
console.log(text.slice(0, 4));  // "Java"
console.log(text.slice(-6));    // "Script"
console.log(text.slice(4, 0));  // "" (empty)

`str.substring(start, end)`

Legacy substring extraction method.

  • Swaps arguments if start > end
  • Treats negative values as 0
  • Avoid using in modern code
const text = "JavaScript";
console.log(text.substring(0, 4));  // "Java"
console.log(text.substring(4, 0));  // "Java" (swapped!)
console.log(text.substring(-4));    // "JavaScript"

⚠️ Deprecation Warning: Avoid `substr()`

str.substr(start, length) is a deprecated legacy method. Always use str.slice(start, end) in modern JavaScript development.

5. Searching & Inspecting Strings

Modern JavaScript provides intuitive boolean and index-based searching methods:

const file = "user-avatar.png";

// 1. Boolean check methods (ES6+)
console.log(file.includes("avatar"));   // true
console.log(file.startsWith("user"));   // true
console.log(file.endsWith(".png"));     // true
console.log(file.endsWith(".jpg"));     // false

// 2. Index finders
console.log(file.indexOf("avatar"));    // 5 (starting index)
console.log(file.indexOf("profile"));   // -1 (not found)
console.log(file.lastIndexOf("-"));    // 4 (last occurrence)
Output
true
true
true
false
5
-1
4

💡 The Index 0 Truthy/Falsy Pitfall

When checking if a substring exists, avoid writing if (str.indexOf("text")). If "text" is found at index 0, JavaScript coerces 0 to false! Always use str.includes("text") or compare explicitly with str.indexOf("text") !== -1.

6. Transforming & Formatting Strings

Common transformations used for input sanitization, UI formatting, and data normalization:

// 1. Trimming Whitespace
const raw = "   hello@domain.com \n ";
console.log(raw.trim());       // "hello@domain.com"
console.log(raw.trimStart());  // "hello@domain.com \n "

// 2. Case Normalization
const role = "aDmIn";
console.log(role.toLowerCase()); // "admin"
console.log(role.toUpperCase()); // "ADMIN"

// 3. String Padding & Repeating
console.log("5".padStart(3, "0"));  // "005" (zero-fill formatted numbers)
console.log("42".padEnd(6, "."));   // "42...."
console.log("La ".repeat(3));       // "La La La "

// 4. replace() vs replaceAll()
const promptText = "cats and cats";
console.log(promptText.replace("cats", "dogs"));    // "dogs and cats" (First match only)
console.log(promptText.replaceAll("cats", "dogs")); // "dogs and dogs" (All matches)
Output
hello@domain.com
admin
ADMIN
005
42....
La La La 
dogs and cats
dogs and dogs

7. The String-Array Bridge: `split()` and `join()`

Converting strings to arrays with .split() and recombining them with .join() is one of the most essential patterns for text parsing, slug generation, and data cleaning:

// 1. String to Words Array
const heading = "Master Modern JavaScript Today";
const words = heading.split(" ");
console.log(words); // ["Master", "Modern", "JavaScript", "Today"]

// 2. Generating a URL Slug
const slug = words.map(w => w.toLowerCase()).join("-");
console.log(slug); // "master-modern-javascript-today"

// 3. Reversing a String
const reversed = "frontend".split("").reverse().join("");
console.log(reversed); // "dnetnorf"

// 4. Extracting CSV Values
const csvRow = "Alex,24,Engineer,London";
const [userName, age, roleTitle, city] = csvRow.split(",");
console.log(`${userName} is a ${roleTitle} in ${city}.`);
Output
[ 'Master', 'Modern', 'JavaScript', 'Today' ]
master-modern-javascript-today
dnetnorf
Alex is a Engineer in London.

8. Quick Reference: Common String Methods

Method Description Example Result
.slice(start, end) Extracts portion by indices (supports negative) "code".slice(1, 3) "od"
.at(index) Character at index (supports negative) "code".at(-1) "e"
.includes(search) Checks if substring exists "api".includes("p") true
.startsWith(prefix) Checks beginning of string "https://".startsWith("http") true
.trim() Removes leading and trailing whitespace " hi ".trim() "hi"
.padStart(len, char) Pads start to target length "7".padStart(3, "0") "007"
.replaceAll(sub, new) Replaces all occurrences "a-b-c".replaceAll("-", ":") "a:b:c"
.split(separator) Splits string into array "a,b".split(",") ["a", "b"]

9. Strings Interview Deck

Test your understanding of string immutability, index slice bounds, search methods, and modern replace utilities:

🎯 Strings Interview Deck
Question 1 of 5
⭐ Easy • String Immutability Immutability
let word = "hello";
word[0] = "H";
console.log(word);
What will be printed to the console?
A) "Hello"
B) "hello"
C) TypeError
D) undefined
⚡ Medium • Negative Indices slice vs substring
const text = "JavaScript";
console.log(text.slice(-6), text.substring(-6));
What will be printed to the console?
A) "Script", "Script"
B) "Java", "Script"
C) "Script", "JavaScript"
D) "", "JavaScript"
⭐ Easy • Replace Methods replace vs replaceAll
const phrase = "dog dog dog";
console.log(phrase.replace("dog", "cat"));
What will be printed to the console?
A) "cat dog dog"
B) "cat cat cat"
C) "dog dog cat"
D) TypeError
⚡ Medium • Index 0 Falsy Trap indexOf() Checks
const msg = "hello world";
if (msg.indexOf("hello")) {
    console.log("Found");
} else {
    console.log("Not found");
}
What will be printed to the console?
A) "Found"
B) "Not found"
C) true
D) TypeError
⭐ Easy • String Reversal Array Bridge
const word = "Javascript";
console.log(word.split("").reverse().join(""));
What is the output?
A) "Javascript"
B) ['t','p','i','r','c','s','a','v','a','J']
C) "tpircsavaJ"
D) undefined

10. Practice Challenges

🎯 Coding Challenge: String Processing & Sanitization

1. Clean rawInput by trimming whitespace and verify if it starts with "https://".
2. Split the URL path segments and retrieve the user ID (4590) using modern .at().
3. Mask the credit card string "1234567890123456" to show only the last 4 digits (e.g. "************3456") using .slice() and .padStart().

Your output will appear here.