Strings are everywhere in JavaScript — parsing URLs, processing user input, building UI labels, talking to APIs. Yet a lot of developers reach for regex or manual loops when a built-in string method would do the job cleaner and faster.
This guide covers the string methods worth memorising in 2026, grouped by what you're trying to do.
Searching and Testing
includes()
'hello world'.includes('world') // true
'hello world'.includes('World') // false — case sensitive
Use this instead of indexOf() !== -1. Cleaner intent, same performance.
startsWith() / endsWith()
'https://example.com'.startsWith('https') // true
'report.csv'.endsWith('.csv') // true
// With a position argument
'hello world'.startsWith('world', 6) // true — starts at index 6
Useful for file type checks, URL validation, and protocol detection.
indexOf() / lastIndexOf()
'banana'.indexOf('a') // 1
'banana'.lastIndexOf('a') // 5
'banana'.indexOf('x') // -1 (not found)
Still useful when you need the actual position, not just a boolean.
Extracting Parts
slice(start, end)
'hello world'.slice(6) // 'world'
'hello world'.slice(0, 5) // 'hello'
'hello world'.slice(-5) // 'world' — negative counts from end
The go-to for extracting substrings. end is exclusive (not included in result).
substring(start, end)
Works like slice but doesn't accept negative indices. Prefer slice in modern code.
at(index)
'hello'.at(0) // 'h'
'hello'.at(-1) // 'o' — last character
'hello'.at(-2) // 'l'
Cleaner than str[str.length - 1] for accessing from the end.
Transforming
toUpperCase() / toLowerCase()
'Hello World'.toUpperCase() // 'HELLO WORLD'
'Hello World'.toLowerCase() // 'hello world'
trim() / trimStart() / trimEnd()
' hello world '.trim() // 'hello world'
' hello world '.trimStart() // 'hello world '
' hello world '.trimEnd() // ' hello world'
Always trim user input before comparison or storage.
replace() / replaceAll()
'foo bar foo'.replace('foo', 'baz') // 'baz bar foo' — first match only
'foo bar foo'.replaceAll('foo', 'baz') // 'baz bar baz'
// With regex
'hello WORLD'.replace(/[A-Z]+/g, match => match.toLowerCase()) // 'hello world'
padStart() / padEnd()
'5'.padStart(3, '0') // '005' — zero-pad numbers
'hi'.padEnd(10, '.') // 'hi........'
Common for formatting IDs, timestamps, and table output.
repeat()
'ha'.repeat(3) // 'hahaha'
'-'.repeat(40) // '----------------------------------------'
Splitting and Joining
split(separator)
'a,b,c'.split(',') // ['a', 'b', 'c']
'hello'.split('') // ['h', 'e', 'l', 'l', 'o']
'hello'.split('', 3) // ['h', 'e', 'l'] — limit
'a b c'.split(/\s+/) // ['a', 'b', 'c'] — regex separator
Pair with Array.join() to transform and reassemble:
'hello world'
.split(' ')
.map(word => word[0].toUpperCase() + word.slice(1))
.join(' ')
// 'Hello World' — basic title case
Matching with Regex
match() / matchAll()
'test 123 foo 456'.match(/\d+/g) // ['123', '456']
'test 123 foo 456'.match(/\d+/) // ['123', index: 5, ...]
// matchAll gives full match objects (requires /g flag)
const matches = [...'foo 123 bar 456'.matchAll(/(\w+)\s(\d+)/g)]
matches[0][1] // 'foo', matches[0][2] // '123'
search(regex)
'hello world'.search(/world/) // 6 (index of match)
'hello world'.search(/xyz/) // -1
Like indexOf but accepts regex.
Comparing
localeCompare()
['banana', 'Apple', 'cherry'].sort((a, b) => a.localeCompare(b))
// ['Apple', 'banana', 'cherry'] — case-insensitive sort
// Language-aware comparison
'é'.localeCompare('e', 'fr') // correctly handles accented characters
Don't use < or > for string sorting — they compare Unicode code points, not linguistic order.
Template Literals (not a method, but worth including)
const name = 'world'
const greeting = `Hello, ${name}!` // 'Hello, world!'
// Multiline
const html = `
<div class="card">
<h2>${title}</h2>
<p>${description}</p>
</div>
`
// Tagged templates (advanced)
const result = sql`SELECT * FROM users WHERE id = ${userId}`
Tagged templates are used in libraries like styled-components and graphql-tag — worth understanding even if you don't write your own.
Quick Reference Table
| Method | What it does |
|---|---|
includes(s) |
Returns true if string contains s
|
startsWith(s) |
Returns true if string starts with s
|
endsWith(s) |
Returns true if string ends with s
|
indexOf(s) |
Position of first match, -1 if not found |
slice(start, end) |
Extract substring |
at(i) |
Character at index (supports negative) |
toUpperCase() |
All uppercase |
toLowerCase() |
All lowercase |
trim() |
Remove leading/trailing whitespace |
replace(s, r) |
Replace first match |
replaceAll(s, r) |
Replace all matches |
padStart(n, c) |
Pad to length n with char c
|
split(sep) |
Split into array |
match(rx) |
Find matches |
localeCompare(s) |
Linguistically correct comparison |
Practical Example: Normalising User Input
Here's a common real-world task — taking raw user input and normalising it for storage:
function normaliseInput(raw) {
return raw
.trim()
.toLowerCase()
.replace(/\s+/g, ' ') // collapse multiple spaces to one
.replace(/[^a-z0-9 ]/g, '') // remove special characters
}
normaliseInput(' Hello World!! ') // 'hello world'
And for slug generation (URL-friendly strings):
function toSlug(title) {
return title
.toLowerCase()
.trim()
.replace(/\s+/g, '-')
.replace(/[^a-z0-9-]/g, '')
}
toSlug('Hello World: A Guide') // 'hello-world-a-guide'
If you work with text a lot and need to quickly switch between camelCase, snake_case, kebab-case, UPPER_CASE and more, the SnappyTools Case Converter handles all common formats in one click — no setup, runs entirely in your browser.
Top comments (0)