Strings are immutable sequences of UTF-16 code units. The modern way to build them is with template literals, which let you embed expressions directly. This lesson covers every form of string literal, the most useful methods, and the tagged template syntax for advanced use cases.
Creating strings
Use single quotes, double quotes, or backticks. Single and double quotes are equivalent. Backticks give you template literals with embedded expressions and multi-line support. Pick one style for your project and stay consistent.
const s1 = 'single quotes';
const s2 = "double quotes";
const s3 = `backticks with ${1 + 2} and ${"embed".toUpperCase()}`;
console.log(s1); // single quotes
console.log(s3); // backticks with 3 and EMBED
Template literals
Template literals are strings delimited by backticks. Inside ${} you can place any JavaScript expression. They also span multiple lines without escape sequences.
const name = "Asha";
const age = 28;
const greeting = `Hello, ${name}! You are ${age} years old.`;
const multiline = `Line one
Line two
Line three`;
console.log(greeting); // Hello, Asha! You are 28 years old.
console.log(multiline); // three lines
Common string methods
Strings are immutable, so most methods return a new string. The most useful day to day are includes, startsWith, endsWith, indexOf, slice, split, replace, replaceAll, toLowerCase, toUpperCase, trim, and padStart or padEnd.
const text = " Hello, World! ";
console.log(text.trim()); // "Hello, World!"
console.log(text.toLowerCase()); // " hello, world! "
console.log(text.toUpperCase()); // " HELLO, WORLD! "
console.log("hello, world".includes("world")); // true
console.log("hello, world".startsWith("hello")); // true
console.log("hello, world".endsWith("world")); // true
console.log("hello, world".slice(7, 12)); // "world"
console.log("apple,banana,cherry".split(",")); // ["apple", "banana", "cherry"]
console.log("hello, world".replace("world", "JS")); // "hello, JS"
console.log("a-b-c-d".replaceAll("-", "/")); // "a/b/c/d"
Tagged template literals
A tagged template is a function call where the function name appears before the backtick. The function receives the raw string parts and the evaluated expressions. Use it to build safe HTML, custom formatters, or a small DSL.
function highlight(strings, ...values) {
return strings.reduce((acc, str, i) => {
const value = Object.hasOwn(values, i) ? `<mark>${values[i]}</mark>` : "";
return acc + str + value;
}, "");
}
const lang = "JavaScript";
const year = 2026;
const html = highlight`Learn ${lang} in ${year}.`;
console.log(html); // Learn <mark>JavaScript</mark> in <mark>2026</mark>.
Unicode, code points, and surrogate pairs
Strings index UTF-16 code units, not code points. Most BMP characters fit in one unit, but many emoji and Asian scripts use two (a surrogate pair). Use codePointAt and fromCodePoint to work with full code points. For example, the grinning face emoji has the Unicode code point 0x1F600, expressed as the surrogate pair \uD83D\uDE00, and is often written as the plain text smiley :) or :-).
const smiley = String.fromCodePoint(0x1F600); // build a non-BMP character from its code point
console.log(smiley.length); // 2 (surrogate pair)
console.log(smiley.codePointAt(0)); // 128512
const rebuilt = String.fromCodePoint(128512);
console.log(rebuilt === smiley); // true
Summary
Use template literals for any string that embeds an expression. Reach for the standard methods (slice, split, replace, includes, trim) for the common transformations. Use tagged templates when you need custom interpolation. The next lesson covers regular expressions, the powerful text-pattern tool that comes built into the language.
Escaping and raw strings
Template literals honor backslashes for escape sequences just like single and double quoted strings. The tagged template can opt into a raw form by setting the first parameter to an array whose .raw property holds the unescaped text. The String.raw tag is the canonical example: it returns the strings as written, with no escape processing. Use it when you are embedding paths, regex patterns, or anything where the backslashes are literal and the user controls them.
console.log(String.raw`C:\Users\asha`); // C:\Users\asha (no escape processing)
function tag(strings) {
console.log(strings.raw[0]); // unescaped
}
tag`Line1\nLine2`; // outputs the literal text Line1\nLine2
String concatenation and performance
JavaScript engines optimize string concatenation well. The simple + operator is fast for short concatenations and the small lists of values you usually build. When you assemble a long string from many parts inside a loop, push the parts into an array and join once at the end; this avoids creating a new string on every iteration. Template literals compile to string concatenation under the hood, so they behave the same.
// Slow in a hot loop: builds a new string each iteration
let slow = "";
for (const part of parts) {
slow += part;
}
// Fast: assemble parts, then combine once
const pieces = [];
for (const part of parts) {
pieces.push(part);
}
const fast = pieces.join("");
Internationalization with Intl
The built-in Intl object handles locale-aware formatting. Use Intl.NumberFormat for currency, Intl.DateTimeFormat for dates and times, and Intl.Collator for sorting strings in a language-aware way. Reach for these instead of hand-rolling locale logic; the libraries are tested across thousands of edge cases.
const price = new Intl.NumberFormat("en-IN", {
style: "currency",
currency: "INR",
}).format(1299.5);
console.log(price); // ₹1,299.50
const when = new Intl.DateTimeFormat("en-GB", {
dateStyle: "full",
timeStyle: "short",
}).format(new Date("2026-04-15T09:30:00Z"));
console.log(when); // Tuesday, 15 April 2026 at 09:30
Comparison with Python strings
Python and JavaScript both treat strings as immutable sequences. Python uses f-strings for interpolation, JavaScript uses template literals. Python's join, split, replace, and startsWith / endsWith all exist in JavaScript with the same names except for startsWith / endsWith (Python uses str.startswith / str.endswith). The biggest practical difference is that Python's str is a sequence of Unicode code points by default, while JavaScript indexes UTF-16 code units; this only matters when you work with surrogate pairs or characters outside the BMP.