JavaScript Strings & Template Literals: Every Method You Need to Know
Strings are sequences of characters and the most common data type in web development. Every user input, every API response, every URL, every HTML element — strings are everywhere. JavaScript gives you an incredibly rich set of tools for working with them. Let us cover every one.
Creating strings
JavaScript offers three ways to create string literals, each with different capabilities.
// Single quotes — the most common in many codebases
const single = 'Hello, world!';
// Double quotes — identical behavior to single quotes
const double = "Hello, world!";
// Template literals (backticks) — the most powerful
const template = \`Hello, world!\`;
// When to use which:
// - Pick single OR double for your project and be consistent
// - Use template literals when you need interpolation or multi-line strings
// - Use the other quote type to avoid escaping:
const html = 'Hello'; // double quotes inside single
const msg = "It's a sunny day"; // apostrophe inside double
const both = \`She said "it's fine"\`; // backticks avoid both issues
Template literals — modern JavaScript’s best feature for strings
// Expression interpolation with \${}
const name = 'Ada';
const age = 30;
console.log(\`My name is \${name} and I am \${age} years old.\`);
// Any expression works inside \${}
console.log(\`2 + 2 = \${2 + 2}\`); // '2 + 2 = 4'
console.log(\`Upper: \${'hello'.toUpperCase()}\`); // 'Upper: HELLO'
console.log(\`Even: \${10 % 2 === 0 ? 'yes' : 'no'}\`); // 'Even: yes'
console.log(\`Items: \${[1,2,3].join(', ')}\`); // 'Items: 1, 2, 3'
// Multi-line strings (preserves whitespace and newlines)
const poem = \`Roses are red,
Violets are blue,
JavaScript strings
Are powerful too.\`;
// Nested template literals
const items = ['apple', 'banana', 'cherry'];
const list = \`
<ul>
\${items.map(item => \`<li>\${item}</li>\`).join('\n ')}
</ul>
\`;
// Raw strings — ignore escape sequences
String.raw\`Hello\nWorld\`; // 'Hello\\nWorld' (literal backslash-n, not newline)
String.raw\`C:\\Users\\name\`; // 'C:\\Users\\name' (great for Windows paths)
Tagged template literals
Tagged templates let you process a template literal with a function. This is how libraries like styled-components, lit-html, and GraphQL work.
// A tag function receives the string parts and interpolated values
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
const value = values[i] !== undefined ? \`<mark>\${values[i]}</mark>\` : '';
return result + str + value;
}, '');
}
const name = 'Ada';
const role = 'engineer';
const html = highlight\`Hello, \${name}! You are an \${role}.\`;
// 'Hello, <mark>Ada</mark>! You are an <mark>engineer</mark>.'
// Practical: SQL-safe queries (prevent injection)
function sql(strings, ...values) {
const escaped = values.map(v => typeof v === 'string' ? v.replace(/'/g, "''") : v);
return strings.reduce((q, str, i) => q + str + (escaped[i] ?? ''), '');
}
// Practical: Internationalization
function i18n(strings, ...values) {
// Look up translated template, fill in values
const key = strings.join('{}');
const translated = translations[key] || strings.join('');
return translated.replace(/\{\}/g, () => values.shift());
}
Essential string methods
Searching and testing
const str = 'JavaScript is awesome and JavaScript is everywhere';
// includes() — does the string contain a substring?
str.includes('awesome') // true
str.includes('python') // false
str.includes('Script', 5) // true (start searching from index 5)
// startsWith() / endsWith()
str.startsWith('Java') // true
str.startsWith('Script', 4) // true (from position 4)
str.endsWith('everywhere') // true
// indexOf() / lastIndexOf() — find position of substring
str.indexOf('JavaScript') // 0
str.lastIndexOf('JavaScript') // 25
str.indexOf('Python') // -1 (not found)
// search() — find position using regex
str.search(/awesome/) // 14
str.search(/python/i) // -1
// match() — extract matches
'price: $42.99'.match(/\d+\.\d+/) // ['42.99']
'a1b2c3'.match(/\d/g) // ['1', '2', '3']
// matchAll() — all matches with groups (returns iterator)
const text = 'Call 555-1234 or 555-5678';
const matches = [...text.matchAll(/(\d{3})-(\d{4})/g)];
// matches[0][0] = '555-1234', matches[0][1] = '555', matches[0][2] = '1234'
Extracting substrings
const str = 'Hello, World!';
// slice(start, end) — the RECOMMENDED method
str.slice(0, 5) // 'Hello'
str.slice(7) // 'World!'
str.slice(-6) // 'orld!' — negative index counts from end
str.slice(-6, -1) // 'orld'
str.slice(7, 12) // 'World'
// substring(start, end) — similar to slice but no negative indices
str.substring(0, 5) // 'Hello'
str.substring(7) // 'World!'
str.substring(12, 7) // 'World' (swaps if start > end)
// at() — access single character (ES2022, supports negative index)
str.at(0) // 'H'
str.at(-1) // '!'
str.at(-2) // 'd'
// charAt() — older way to access characters
str.charAt(0) // 'H'
str.charAt(99) // '' (empty string if out of range)
// Bracket notation — also works
str[0] // 'H'
str[str.length - 1] // '!'
Transforming strings
// Case conversion
'hello'.toUpperCase() // 'HELLO'
'HELLO'.toLowerCase() // 'hello'
// Locale-aware case conversion (for Turkish, German, etc.)
'istanbul'.toLocaleUpperCase('tr') // 'İSTANBUL' (dotted İ)
// Trimming whitespace
' hello '.trim() // 'hello'
' hello '.trimStart() // 'hello '
' hello '.trimEnd() // ' hello'
// Padding
'5'.padStart(3, '0') // '005'
'42'.padStart(5, ' ') // ' 42'
'hi'.padEnd(10, '.') // 'hi........'
'abc'.padEnd(6, '12') // 'abc121'
// Repeating
'ha'.repeat(3) // 'hahaha'
'-'.repeat(40) // '----------------------------------------'
// Replacing
'hello world'.replace('world', 'JS') // 'hello JS'
'aabbcc'.replace('b', 'X') // 'aaXbcc' (first match only)
'aabbcc'.replaceAll('b', 'X') // 'aaXXcc' (all matches)
'hello'.replace(/[aeiou]/g, '*') // 'h*ll*' (regex)
// Replace with a function
'hello world'.replace(/\b\w/g, char => char.toUpperCase());
// 'Hello World' (capitalize first letter of each word)
// Splitting
'a,b,c'.split(',') // ['a', 'b', 'c']
'hello'.split('') // ['h', 'e', 'l', 'l', 'o']
'one two three'.split(/\s+/) // ['one', 'two', 'three']
'a,b,c,d'.split(',', 2) // ['a', 'b'] (limit to 2 parts)
// Concatenation (use template literals instead)
'Hello'.concat(' ', 'World') // 'Hello World'
String comparison
// Strings are compared character by character using Unicode code points
'a' < 'b' // true (97 < 98)
'B' < 'a' // true (66 < 97 — uppercase letters come first!)
'10' < '9' // true ('1' < '9' — comparing as strings, not numbers!)
'abc' < 'abd' // true (first difference: 'c' < 'd')
'' < 'a' // true (empty string is "less than" everything)
// For locale-aware sorting, use localeCompare
'ä'.localeCompare('z', 'de') // -1 (in German, ä comes before z)
'ä'.localeCompare('z', 'sv') // 1 (in Swedish, ä comes after z)
// Case-insensitive comparison
'Hello'.toLowerCase() === 'hello'.toLowerCase() // true
// Sorting an array of strings properly
const words = ['banana', 'Apple', 'cherry'];
words.sort() // ['Apple', 'banana', 'cherry'] (uppercase first!)
words.sort((a, b) => a.localeCompare(b)) // ['Apple', 'banana', 'cherry'] (locale-aware)
Unicode and emoji
// JavaScript strings are UTF-16 encoded
// Most characters use one 16-bit code unit
'A'.length // 1
'€'.length // 1
// But emoji and some characters use TWO code units (surrogate pairs)
'😀'.length // 2 (!)
'𝕳'.length // 2
// This breaks naive character counting
'Hello 😀'.length // 8 (not 7!)
// Fix: use Array.from or spread to get actual characters
[...'Hello 😀'].length // 7 (correct!)
Array.from('Hello 😀').length // 7
// Iterating correctly over Unicode
for (const char of 'Hi 😀') {
console.log(char); // 'H', 'i', ' ', '😀' (correct)
}
// Unicode escape sequences
'\u0041' // 'A'
'\u{1F600}' // '😀' (for code points above U+FFFF)
// codePointAt / fromCodePoint (modern, handles full Unicode)
'😀'.codePointAt(0) // 128512
String.fromCodePoint(128512) // '😀'
String.fromCodePoint(65, 66) // 'AB'
// Normalize for comparison (accented characters can be encoded two ways)
'café'.normalize() === 'caf\u0065\u0301'.normalize() // true
Practical string patterns
// Truncate with ellipsis
function truncate(str, maxLen) {
return str.length > maxLen ? str.slice(0, maxLen - 3) + '...' : str;
}
truncate('This is a long sentence', 15); // 'This is a lo...'
// Capitalize first letter
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
capitalize('hello'); // 'Hello'
// Convert to title case
function titleCase(str) {
return str.replace(/\b\w/g, c => c.toUpperCase());
}
titleCase('hello world from javascript'); // 'Hello World From Javascript'
// Slugify (for URLs)
function slugify(str) {
return str
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, '') // remove non-word chars
.replace(/\s+/g, '-') // spaces to hyphens
.replace(/-+/g, '-'); // collapse multiple hyphens
}
slugify('Hello World! This is Cool'); // 'hello-world-this-is-cool'
// Extract domain from email
function getDomain(email) {
return email.split('@')[1];
}
getDomain('user@example.com'); // 'example.com'
// Mask sensitive data
function maskEmail(email) {
const [user, domain] = email.split('@');
return user[0] + '*'.repeat(user.length - 2) + user.at(-1) + '@' + domain;
}
maskEmail('chirag@example.com'); // 'c****g@example.com'
// Count occurrences of a substring
function countOccurrences(str, sub) {
return str.split(sub).length - 1;
}
countOccurrences('banana', 'an'); // 2
// Reverse a string (Unicode-safe)
function reverse(str) {
return [...str].reverse().join('');
}
reverse('Hello 😀'); // '😀 olleH'
// Check if palindrome
function isPalindrome(str) {
const clean = str.toLowerCase().replace(/[^a-z0-9]/g, '');
return clean === [...clean].reverse().join('');
}
isPalindrome('A man, a plan, a canal: Panama'); // true
String immutability
Strings in JavaScript are immutable. Every string method returns a new string — the original is never modified.
const original = 'hello';
const upper = original.toUpperCase();
console.log(original); // 'hello' (unchanged)
console.log(upper); // 'HELLO' (new string)
// You cannot change individual characters
original[0] = 'H'; // Silently fails (no error, no change)
// You must create a new string
const fixed = 'H' + original.slice(1); // 'Hello'
// This is why chaining creates new strings at each step
const result = ' Hello, World! '
.trim() // new string: 'Hello, World!'
.toLowerCase() // new string: 'hello, world!'
.replace('world', 'js'); // new string: 'hello, js!'
Strings are one of the most heavily used types in JavaScript, and mastering them means mastering half of web development. Template literals for building strings, the method arsenal for transforming them, and understanding immutability — these are the tools you will use every single day.