Skip to content
C Codeloom
JavaScript

Strings and Template Literals in JavaScript

A practical guide to JavaScript strings — template literals, indexing, the essential methods, immutability, and the modern ways to slice, search, and transform text.

·7 min read · By Yash Kesharwani
Beginner 10 min read

What you'll learn

  • The three string syntaxes and when to use each
  • Template literals for interpolation and multi-line text
  • Indexing, slicing, and length
  • The string methods you will use constantly
  • Why strings are immutable and what that means in practice

Prerequisites

A string is a sequence of text characters, and there is almost no program that doesn’t touch one. JavaScript’s string API is small enough to learn in an afternoon and rich enough to cover most everyday text work.

Creating strings

Three quote styles, all producing equivalent string values:

const a = "double quotes";
const b = 'single quotes';
const c = `backticks`;

Single and double quotes are interchangeable — pick one style and stick with it. Backticks (also called template literals) are different and worth learning well.

Escape sequences

If your text contains the same quote you used to wrap it, escape it with a backslash:

const a = "She said \"hello\".";
const b = 'It\'s a trap.';

Or use the other quote style:

const a = 'She said "hello".';
const b = "It's a trap.";

Common escapes:

"line one\nline two"      // newline
"col1\tcol2"              // tab
"a backslash: \\"         // literal backslash

Template literals

Backtick strings unlock two superpowers that double and single quotes lack.

1. Interpolation

The ${...} syntax embeds any JavaScript expression directly inside the string:

const name = "Ada";
const age = 30;
console.log(`${name} is ${age} years old.`);
// 'Ada is 30 years old.'

const a = 7, b = 5;
console.log(`The sum of ${a} and ${b} is ${a + b}.`);
// 'The sum of 7 and 5 is 12.'

This replaces string concatenation. In older code you would have written:

console.log(name + " is " + age + " years old.");

That still works but is harder to read. Use template literals.

2. Multi-line strings

Backtick strings can span multiple lines without escape sequences:

const message = `Hello,

This is a multi-line string.
Whitespace and newlines are preserved exactly.

— The Codeloom Team`;

console.log(message);

For both reasons, modern style uses backticks freely.

Length and indexing

.length gives you the number of characters:

const s = "hello";
console.log(s.length);    // 5

Index characters with square brackets, zero-based:

console.log(s[0]);        // 'h'
console.log(s[4]);        // 'o'
console.log(s[s.length - 1]);  // 'o'  — last character
console.log(s[99]);       // undefined

There is no Python-style s[-1] for “last character”. Use s.at(-1) instead, which is the modern equivalent:

console.log(s.at(-1));    // 'o'
console.log(s.at(-2));    // 'l'

Strings are immutable

You cannot change a character inside an existing string:

let s = "hello";
s[0] = "H";          // silently does nothing
console.log(s);      // 'hello'

To “change” a string, you build a new one and reassign:

let s = "hello";
s = "H" + s.slice(1);
console.log(s);      // 'Hello'

This may feel restrictive coming from languages with mutable strings, but it is the norm — Python, Java, and C# all do the same. Strings are values, not containers.

Slicing with slice

slice(start, end) returns a portion of a string. end is exclusive, and both arguments can be negative to count from the end:

const s = "JavaScript";
console.log(s.slice(0, 4));    // 'Java'
console.log(s.slice(4));        // 'Script'
console.log(s.slice(-6));       // 'Script'
console.log(s.slice(-6, -3));   // 'Scr'

If you’ve used Python, this is the equivalent of s[start:end].

Common string methods

A small set of methods covers most everyday text work.

Searching

const s = "the quick brown fox";

s.includes("quick");      // true
s.startsWith("the");      // true
s.endsWith("fox");        // true
s.indexOf("brown");       // 10
s.indexOf("cat");         // -1  (not found)

Case

"hello".toUpperCase();    // 'HELLO'
"HELLO".toLowerCase();    // 'hello'

Trimming whitespace

"   hello   ".trim();         // 'hello'
"   hello   ".trimStart();    // 'hello   '
"   hello   ".trimEnd();      // '   hello'

.trim() is what you want when reading user input — it removes accidental spaces and newlines at both ends.

Replacing

const s = "I like cats. Cats are great.";

s.replace("cats", "dogs");      // 'I like dogs. Cats are great.'  — first only
s.replaceAll("cats", "dogs");   // 'I like dogs. Cats are great.'
s.replaceAll(/cats/gi, "dogs"); // 'I like dogs. dogs are great.'  — case-insensitive regex

replaceAll requires a regex with the global flag, or a plain string. replace only swaps the first occurrence unless you pass a global regex.

Splitting and joining

const csv = "Alice,Bob,Carol";
const names = csv.split(",");
console.log(names);                  // ['Alice', 'Bob', 'Carol']

console.log(names.join(" and "));    // 'Alice and Bob and Carol'

"hello".split("");                   // ['h','e','l','l','o']

split and join are the workhorses for converting between strings and arrays.

Padding and repeating

"7".padStart(3, "0");      // '007'
"7".padEnd(3, "-");        // '7--'
"abc".repeat(3);           // 'abcabcabc'

padStart is great for things like zero-padded numbers, time displays, and tabular output.

Try it yourself. Write a function initials(fullName) that returns the uppercase initials of a name. For example, initials("ada lovelace") should return "AL". Use split, map (we’ll cover it formally with arrays), and join.

function initials(fullName) {
  return fullName
    .split(" ")
    .map((word) => word[0].toUpperCase())
    .join("");
}
console.log(initials("ada lovelace"));   // 'AL'

Comparing strings

Use === for equality:

"hello" === "hello";    // true
"hello" === "Hello";    // false  — case matters

The comparison operators <, >, <=, >= compare strings lexicographically, character by character using Unicode code point order:

"apple" < "banana";     // true
"Banana" < "apple";     // true   — uppercase letters come before lowercase

For case-insensitive comparison, lowercase both sides first:

"Apple".toLowerCase() === "apple".toLowerCase();   // true

For locale-aware sorting (à before z in French, for instance), use localeCompare:

["zebra", "apple", "élan"].sort((a, b) => a.localeCompare(b));

Converting between strings and other types

We mentioned this in Data Types, but it bears repeating:

String(42);              // '42'
String(true);            // 'true'
String(null);            // 'null'
(123).toString();        // '123'
(123).toString(2);       // '1111011'  — binary
(255).toString(16);      // 'ff'       — hex

Number("42");            // 42
Number.parseInt("42px"); // 42

For display, toLocaleString (covered in Numbers and Math) handles locale-aware formatting.

Try it yourself. Write a function slugify(title) that turns a string like " My First Blog Post! " into "my-first-blog-post". Lowercase it, trim, split on spaces, filter out empty pieces, and join with -.

A small worked example

A function that takes a list of guests and returns a polite sentence:

function guestList(names) {
  if (names.length === 0) return "Nobody is coming.";
  if (names.length === 1) return `${names[0]} is coming.`;
  if (names.length === 2) return `${names[0]} and ${names[1]} are coming.`;
  const allButLast = names.slice(0, -1).join(", ");
  const last = names.at(-1);
  return `${allButLast}, and ${last} are coming.`;
}

console.log(guestList([]));
console.log(guestList(["Ada"]));
console.log(guestList(["Ada", "Linus"]));
console.log(guestList(["Ada", "Linus", "Grace", "Edsger"]));

Output:

Nobody is coming.
Ada is coming.
Ada and Linus are coming.
Ada, Linus, Grace, and Edsger are coming.

Every concept in this post — template literals, slice, join, at(-1) — earns its keep here.

Recap

You now know:

  • Three quote styles; template literals (backticks) for interpolation and multi-line text
  • Strings are immutable — methods return new strings rather than modifying in place
  • Index with [i]; for negative indices use s.at(-1)
  • slice for substrings, split/join for converting to and from arrays
  • includes, startsWith, endsWith, indexOf for searching
  • replace (first) vs. replaceAll
  • Lexicographic comparison and the localeCompare escape hatch for sorting

Next steps

Strings are sequences of characters. Next, we look at the most-used general-purpose sequence type in JavaScript: arrays.

→ Next: JavaScript Arrays: Create, Iterate, Transform

Questions or feedback? Email codeloomdevv@gmail.com.