Chapter 10 Intermediate 26 min min read Updated 2026-04-09

Strings and Template Literals

Practice Questions →

In This Chapter

What Is It?

What Are Strings in JavaScript?

A string is a sequence of characters used to represent text. Anything enclosed in quotes is a string: a name, a sentence, a password, a URL, or even HTML code. Strings are one of the most commonly used data types in programming.

JavaScript gives you three ways to write strings:

const single = 'Hello';           // Single quotes
const double = "Hello";           // Double quotes
const backtick = `Hello`;         // Backticks (template literals)

Single and double quotes work the same way. Backticks (template literals) are special - they let you embed expressions, create multiline strings, and build dynamic HTML. You will use backticks heavily in web development.

Strings in JavaScript are immutable, meaning once created, they cannot be changed. Every string method returns a new string instead of modifying the original.

Why Does It Matter?

Why Are Strings Important?

Strings are everywhere in web development. Here is why you need to master them:

1. User Input and Forms

Every piece of text a user types into a form - their name, email, password, search query - is a string. You need string methods to validate, clean, and process this input.

2. Building Dynamic HTML

Modern web apps generate HTML dynamically from data. Template literals let you build HTML strings with embedded variables, creating cards, lists, tables, and entire page sections from JavaScript.

3. Working with APIs

API URLs contain parameters as strings. JSON data (from servers) contains strings. HTTP headers, query strings, and response bodies are all text. String manipulation is essential for API work.

4. Text Processing

Searching text, extracting parts, replacing content, formatting dates and numbers, building URLs, parsing CSV data - all of these involve string operations.

5. Template Literals Changed Everything

Before template literals (ES6), building strings with variables was painful: "Hello " + name + ", you are " + age + " years old". Now you write: `Hello ${name}, you are ${age} years old`. This single feature makes JavaScript code dramatically more readable.

Detailed Explanation

Detailed Explanation

1. String Properties and Basic Methods

length gives the number of characters in a string. charAt(index) returns the character at a given position. You can also use bracket notation str[index].

const name = "Aarav";
console.log(name.length);    // 5
console.log(name.charAt(0)); // "A"
console.log(name[4]);        // "v"

2. Searching: indexOf, lastIndexOf, includes, startsWith, endsWith

const text = "JavaScript is amazing and JavaScript is everywhere";

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

text.includes("amazing");   // true
text.startsWith("Java");    // true
text.endsWith("everywhere"); // true

indexOf returns the position of the first match, or -1 if not found. lastIndexOf searches from the end. includes, startsWith, and endsWith return booleans.

3. Extracting Parts: slice and substring

const str = "Hello, World!";

str.slice(0, 5);     // "Hello" (start to end, exclusive)
str.slice(7);        // "World!" (start to end of string)
str.slice(-6);       // "orld!" (negative = from end)
str.substring(0, 5); // "Hello" (similar to slice)

slice is the most commonly used. It takes a start index and an optional end index (exclusive). Negative indices count from the end.

4. Changing Case: toUpperCase and toLowerCase

const name = "Priya Sharma";
name.toUpperCase(); // "PRIYA SHARMA"
name.toLowerCase(); // "priya sharma"

These return new strings. The original is unchanged (strings are immutable).

5. Trimming Whitespace: trim, trimStart, trimEnd

const input = "   hello   ";
input.trim();      // "hello"
input.trimStart(); // "hello   "
input.trimEnd();   // "   hello"

Very useful for cleaning user input from forms.

6. Splitting and Joining: split and join

split breaks a string into an array. join combines an array into a string.

const csv = "Aarav,Priya,Rohan,Diya";
const names = csv.split(","); // ["Aarav", "Priya", "Rohan", "Diya"]

const sentence = names.join(" and "); // "Aarav and Priya and Rohan and Diya"

// Split a sentence into words
"Hello World".split(" "); // ["Hello", "World"]

// Split into individual characters
"Code".split(""); // ["C", "o", "d", "e"]

7. Replacing: replace and replaceAll

const text = "I love Java. Java is great.";

text.replace("Java", "JavaScript");
// "I love JavaScript. Java is great." (only first match)

text.replaceAll("Java", "JavaScript");
// "I love JavaScript. JavaScript is great." (all matches)

replace replaces only the first occurrence. replaceAll replaces every occurrence. Both return new strings.

8. Repeating and Padding: repeat, padStart, padEnd

"Ha".repeat(3);         // "HaHaHa"
"5".padStart(3, "0");   // "005"
"5".padEnd(3, "0");     // "500"
"42".padStart(5, " ");  // "   42"

padStart and padEnd are great for formatting numbers, creating aligned text, and building consistent displays.

9. Template Literals (Backticks)

Template literals use backticks (`) instead of quotes. They have three superpowers:

String Interpolation

Embed expressions directly inside strings using ${expression}:

const name = "Aarav";
const age = 15;

console.log(`Hello, ${name}! You are ${age} years old.`);
// Hello, Aarav! You are 15 years old.

console.log(`Next year you will be ${age + 1}.`);
// Next year you will be 16.

console.log(`${name.toUpperCase()} scored ${85 + 7} marks.`);
// AARAV scored 92 marks.

Any valid JavaScript expression works inside ${}: variables, math, function calls, ternary operators, etc.

Multiline Strings

const poem = `Roses are red,
Violets are blue,
JavaScript is awesome,
And so are you.`;

console.log(poem);

With regular quotes, you would need \n for each new line. Template literals preserve actual line breaks.

10. Building Dynamic HTML with Template Literals

This is one of the most practical uses of template literals. You can build HTML strings from data and insert them into the page:

const student = { name: "Priya", grade: "10th", score: 92 };

const card = `
  

${student.name}

Grade: ${student.grade}

Score: ${student.score}/100

${student.score >= 90 ? "Topper" : "Pass"}
`; document.body.innerHTML += card;

Notice the ternary operator inside ${} - it adds "Topper" or "Pass" based on the score. This is how modern web apps build UI components from data.

11. Building Lists from Arrays

const students = ["Aarav", "Priya", "Rohan", "Diya"];

const listHTML = `
  
    ${students.map(name => `
  • ${name}
  • `).join("\n ")}
`; console.log(listHTML);

This uses map to transform each name into an <li> element, then join to combine them into a single string. The result is a complete HTML list.

12. Tagged Templates (Brief)

Tagged templates let you process a template literal with a function. The function receives the string parts and the values separately:

function highlight(strings, ...values) {
  let result = "";
  strings.forEach((str, i) => {
    result += str;
    if (i < values.length) {
      result += `${values[i]}`;
    }
  });
  return result;
}

const name = "Aarav";
const score = 95;
const html = highlight`${name} scored ${score} marks`;
// Aarav scored 95 marks

Tagged templates are advanced but very powerful. Libraries like styled-components in React use them extensively.

13. String.raw

String.raw is a built-in tagged template that returns the raw string without processing escape sequences:

console.log(`Hello\nWorld`);       // Hello (newline) World
console.log(String.raw`Hello\nWorld`); // Hello\nWorld (literal backslash n)

Useful when you want backslashes to remain as-is, like in file paths or regular expressions.

Code Examples

Essential String Methods
const text = "JavaScript is Fun!";

console.log("Length:", text.length);
console.log("Char at 4:", text.charAt(4));
console.log("Index of 'is':", text.indexOf("is"));
console.log("Includes 'Fun':", text.includes("Fun"));
console.log("Starts with 'Java':", text.startsWith("Java"));
console.log("Ends with '!':", text.endsWith("!"));
console.log("Uppercase:", text.toUpperCase());
console.log("Lowercase:", text.toLowerCase());
These are the most commonly used string methods. length counts characters. charAt/indexOf find positions. includes/startsWith/endsWith check for content. toUpperCase/toLowerCase change case. All return new values without modifying the original.
Length: 18 Char at 4: S Index of 'is': 11 Includes 'Fun': true Starts with 'Java': true Ends with '!': true Uppercase: JAVASCRIPT IS FUN! Lowercase: javascript is fun!
slice, split, join, replace
const email = "aarav.sharma@school.edu";

// slice: extract parts
console.log("Username:", email.slice(0, email.indexOf("@")));
console.log("Domain:", email.slice(email.indexOf("@") + 1));

// split and join
const parts = email.split("@");
console.log("Parts:", parts);

const csv = "Maths,Science,English,Hindi";
const subjects = csv.split(",");
console.log("Subjects:", subjects);
console.log("Joined:", subjects.join(" | "));

// replace
const greeting = "Hello World, Hello Everyone";
console.log(greeting.replace("Hello", "Hi"));
console.log(greeting.replaceAll("Hello", "Hi"));
slice extracts a portion of a string. split breaks a string into an array at each separator. join combines array elements into a string. replace changes the first match; replaceAll changes all matches.
Username: aarav.sharma Domain: school.edu Parts: ["aarav.sharma", "school.edu"] Subjects: ["Maths", "Science", "English", "Hindi"] Joined: Maths | Science | English | Hindi Hi World, Hello Everyone Hi World, Hi Everyone
trim, repeat, padStart, padEnd
// Cleaning user input
const userInput = "   Priya Sharma   ";
console.log("Trimmed:", userInput.trim());

// Repeating strings
console.log("Ha".repeat(5));
console.log("-".repeat(20));

// Padding numbers
const nums = [1, 12, 123, 1234];
nums.forEach(n => {
  console.log(String(n).padStart(6, "0"));
});

// Right-padding
console.log("Price".padEnd(15, ".") + "Rs 500");
trim() removes whitespace from both ends (essential for form input). repeat(n) repeats the string n times. padStart(length, char) pads the beginning to reach the target length. padEnd pads the end.
Trimmed: Priya Sharma HaHaHaHaHa -------------------- 000001 000012 000123 001234 Price..........Rs 500
Template Literals - String Interpolation
const student = {
  name: "Rohan",
  age: 16,
  marks: 88
};

// Basic interpolation
console.log(`Name: ${student.name}`);
console.log(`Age: ${student.age}, Next year: ${student.age + 1}`);

// Expressions inside ${}
console.log(`Status: ${student.marks >= 50 ? "PASS" : "FAIL"}`);
console.log(`Grade: ${student.marks >= 90 ? "A" : student.marks >= 75 ? "B" : "C"}`);

// Function calls inside ${}
console.log(`Uppercase: ${student.name.toUpperCase()}`);
Template literals let you embed any JavaScript expression inside ${}. Variables, math, ternary operators, function calls - anything that evaluates to a value works. This is much cleaner than string concatenation with the + operator.
Name: Rohan Age: 16, Next year: 17 Status: PASS Grade: B Uppercase: ROHAN
Building an HTML Card from a Student Object
const student = {
  name: "Kavya Nair",
  grade: "10th",
  score: 94,
  subjects: ["Maths", "Science", "English"]
};

const card = `
<div class="card">
  <h3>${student.name}</h3>
  <p>Grade: ${student.grade} | Score: ${student.score}/100</p>
  <p>Status: ${student.score >= 90 ? "Distinction" : "Pass"}</p>
  <ul>
    ${student.subjects.map(s => `<li>${s}</li>`).join("\n    ")}
  </ul>
</div>`;

console.log(card);
This generates a complete HTML card from an object. The template literal handles multiline HTML naturally. Inside ${}, we use a ternary for conditional text and map().join() to build a list from an array. This pattern is used constantly in real web development.
<div class="card"> <h3>Kavya Nair</h3> <p>Grade: 10th | Score: 94/100</p> <p>Status: Distinction</p> <ul> <li>Maths</li> <li>Science</li> <li>English</li> </ul> </div>
Building a Dynamic List from an Array
const courses = [
  { name: "JavaScript", level: "Beginner" },
  { name: "React", level: "Intermediate" },
  { name: "Node.js", level: "Advanced" }
];

const html = `
<div class="course-list">
  <h2>Available Courses</h2>
  ${courses.map(c => `
  <div class="course">
    <strong>${c.name}</strong>
    <span class="badge">${c.level}</span>
  </div>`).join("")}
</div>`;

console.log(html);
This builds a complete course listing from an array of objects. Each course is mapped to an HTML div using template literals. The outer template literal wraps everything in a container. This is exactly how components work in frameworks like React.
<div class="course-list"> <h2>Available Courses</h2> <div class="course"> <strong>JavaScript</strong> <span class="badge">Beginner</span> </div> <div class="course"> <strong>React</strong> <span class="badge">Intermediate</span> </div> <div class="course"> <strong>Node.js</strong> <span class="badge">Advanced</span> </div> </div>
Tagged Template Literal
function currency(strings, ...values) {
  let result = "";
  strings.forEach((str, i) => {
    result += str;
    if (i < values.length) {
      result += "Rs " + values[i].toLocaleString();
    }
  });
  return result;
}

const price = 45000;
const tax = 8100;
const total = price + tax;

console.log(currency`Price: ${price}, Tax: ${tax}, Total: ${total}`);
A tagged template is a function that processes a template literal. It receives the string parts and the interpolated values separately. Here, the currency tag automatically formats numbers with "Rs" and commas. This pattern is used in libraries for CSS-in-JS, internationalization, and more.
Price: Rs 45,000, Tax: Rs 8,100, Total: Rs 53,100
String.raw for Escape Sequences
// Normal template literal processes escape sequences
console.log(`Line 1\nLine 2`);

// String.raw keeps backslashes as-is
console.log(String.raw`Line 1\nLine 2`);

// Useful for file paths
const path = String.raw`C:\Users\Aarav\Desktop\project`;
console.log(path);

// Useful for regex patterns
const pattern = String.raw`\d{3}-\d{4}`;
console.log(pattern);
String.raw is a built-in tagged template that returns the raw string without processing escape sequences like \n or \t. This is useful for Windows file paths and regular expression patterns where backslashes should be literal.
Line 1 Line 2 Line 1\nLine 2 C:\Users\Aarav\Desktop\project \d{3}-\d{4}

Common Mistakes

Thinking Strings Are Mutable

let name = "Aarav";
name[0] = "B"; // Trying to change first character
console.log(name); // Still "Aarav" - not "Baarav"!
Strings are immutable. You cannot change individual characters.
let name = "Aarav";
name = "B" + name.slice(1); // Create a new string
console.log(name); // "Baarav"
Strings in JavaScript are immutable. You cannot modify individual characters. To change a string, you must create a new one. All string methods return new strings - they never modify the original.

Forgetting That replace Only Changes the First Match

const text = "cat dog cat bird cat";
const result = text.replace("cat", "fish");
console.log(result); // "fish dog cat bird cat" - only first!
replace only replaces the first occurrence, not all of them.
const text = "cat dog cat bird cat";
const result = text.replaceAll("cat", "fish");
console.log(result); // "fish dog fish bird fish"
replace only changes the first occurrence. Use replaceAll to change all occurrences. Alternatively, you can use a regex with the global flag: text.replace(/cat/g, "fish").

Confusing slice Parameters

const str = "JavaScript";
// Priya thinks slice(3, 6) extracts 4 characters
console.log(str.slice(3, 6)); // "aSc" (only 3 chars, not 4)
slice(start, end) does not include the character at the end index.
const str = "JavaScript";
// slice(start, end) - end is EXCLUSIVE
console.log(str.slice(3, 6)); // "aSc" (indices 3, 4, 5)
console.log(str.slice(3, 7)); // "aScr" (indices 3, 4, 5, 6)
The end index in slice(start, end) is exclusive - the character at that index is NOT included. slice(3, 6) extracts characters at indices 3, 4, and 5. To include index 6, use slice(3, 7).

Using + Instead of Template Literals

const name = "Rohan";
const age = 16;

// Messy string concatenation
const msg = "Hello " + name + ", you are " + age + " years old and will be " + (age + 1) + " next year.";
console.log(msg);
Not an error, but hard to read and maintain with many variables.
const name = "Rohan";
const age = 16;

// Clean template literal
const msg = `Hello ${name}, you are ${age} years old and will be ${age + 1} next year.`;
console.log(msg);
Template literals with ${} are much more readable than string concatenation with +. As strings get more complex (especially with HTML), the readability difference becomes huge. Always prefer template literals for strings with variables.

Not Converting Numbers Before Using padStart

const num = 42;
console.log(num.padStart(5, "0")); // TypeError!
padStart is a string method. Numbers do not have it.
const num = 42;
console.log(String(num).padStart(5, "0")); // "00042"
padStart and padEnd are string methods. You cannot call them on numbers directly. Convert the number to a string first using String(num) or num.toString().

Summary

  • Strings are sequences of characters, created with single quotes, double quotes, or backticks. They are immutable - every string method returns a new string.
  • length gives the character count. charAt(i) or str[i] returns the character at position i. Indices start at 0.
  • indexOf/lastIndexOf find positions. includes/startsWith/endsWith return booleans. indexOf returns -1 when not found.
  • slice(start, end) extracts a portion of a string. The end index is exclusive. Negative indices count from the end. This is the most common extraction method.
  • toUpperCase/toLowerCase change case. trim/trimStart/trimEnd remove whitespace. These are essential for cleaning user input.
  • split breaks a string into an array at each separator. join combines array elements into a string with a separator. These are a powerful pair for text processing.
  • replace changes the first match. replaceAll changes every match. Both return new strings. Use replaceAll when you want to replace all occurrences.
  • Template literals (backticks) enable string interpolation with ${expression}, multiline strings, and embedded expressions. Any valid JavaScript expression works inside ${}.
  • Template literals are the preferred way to build dynamic HTML. Use map().join() inside ${} to generate lists from arrays. Use ternary operators for conditional content.
  • padStart/padEnd pad strings to a target length. repeat(n) repeats a string n times. Convert numbers to strings before using padStart.
  • Tagged templates are functions that process template literals. They receive string parts and values separately. String.raw is a built-in tag that preserves escape sequences.

Ready to Practice?

Test your understanding with 50+ practice questions on this topic.

Go to Practice Questions

Want to learn web development with a live mentor?

Explore our Frontend Masterclass