JavaScript String Methods

Every String prototype method with signature, return type and unicode notes

Searchable JavaScript String method reference. Each entry lists the call signature, return type, and unicode behaviour, with a reminder that strings are immutable so every method returns a new value rather than changing the original. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

Are JavaScript strings mutable?

No. Strings are immutable primitives, so no method changes the string in place. Methods like toUpperCase, replace, and trim all return a brand-new string and leave the original unchanged. You must assign the result to keep it.

JavaScript strings are immutable, so every method here returns a new string or a derived value rather than changing the original. This reference lists each String.prototype method with its signature, return type, and the unicode gotchas that trip people up.

The one rule that prevents most string bugs

Strings are immutable. No String.prototype method ever changes the original string. Every method returns a new value, and if you do not assign that return value, it is lost silently. This trips up developers coming from languages where string mutation is common:

let name = "  alice  ";
name.trim();         // does nothing visible — return value discarded
console.log(name);   // "  alice  " — unchanged

name = name.trim();  // correct — assign the return value
console.log(name);   // "alice"

Method groups

  • SearchindexOf, lastIndexOf, includes, startsWith, endsWith, match, matchAll, search — locate text or patterns.
  • Sliceslice, substring, substr, at — extract a portion of the string.
  • TransformtoUpperCase, toLowerCase, toLocaleLowerCase, trim, trimStart, trimEnd, padStart, padEnd, replace, replaceAll, repeat, normalize — produce a new transformed string.
  • Convertsplit, charAt, charCodeAt, codePointAt, fromCharCode, localeCompare — move between strings, arrays, and numeric code points.

Because strings are immutable, none of these mutate this; you always keep the return value.

The slice vs substring vs substr trap

These three look similar but behave differently at the edges:

MethodNegative indicesArgument meaning
slice(start, end)Counts from end of stringStart and end positions
substring(start, end)Clamps negatives to 0; swaps args if start > endStart and end positions
substr(start, length)Negative start counts from endStart position and length

substr is legacy and its removal from the standard has been discussed. Prefer slice for predictable behaviour with negative indices.

The replace vs replaceAll trap

replace with a string pattern only replaces the first match. replaceAll replaces every occurrence. Forgetting this is one of the most common JavaScript string bugs:

"foo foo foo".replace("foo", "bar")    // "bar foo foo"
"foo foo foo".replaceAll("foo", "bar") // "bar bar bar"

If you pass a regex to replaceAll, it must have the g (global) flag or a TypeError is thrown.

Unicode pitfalls

length counts UTF-16 code units, not characters. Characters outside the Basic Multilingual Plane (many emoji, some CJK extension characters) are encoded as two code units (a surrogate pair). A single emoji can have a .length of 2.

"A".length    // 1
"😀".length   // 2

To count visible characters: [..."😀"].length gives 1 because spread and for...of iterate over Unicode code points, not code units.

normalize for reliable comparison. The same visible character can have multiple Unicode representations — for example “é” as a single precomposed code point or as “e” followed by a combining accent. They look identical but are not === equal. Always normalise before comparison or search:

"café".normalize("NFC") === "café".normalize("NFC") // true even with different source encodings

Practical decision guide

  • Need the position of a match? → indexOf / lastIndexOf
  • Just need to know if a string is present? → includes (cleaner than indexOf !== -1)
  • Extracting a portion? → slice (prefer over substring)
  • Replacing all occurrences of a literal string? → replaceAll
  • Padding a number string to fixed width? → padStart
  • Splitting into words or tokens? → split
  • Comparing user-entered text that might have different Unicode encodings? → normalize('NFC') first