JavaScript: Strings
Master string creation, template literals, escape characters, immutability, and every essential string method.
String Creation
Strings can be created as primitives using literals (the standard approach) or as objects using the String constructor. Always use literals, the constructor creates an object, not a primitive, which causes unexpected behaviour with equality checks.
String Literals vs Constructor
Three quote styles for literals, backticks are the most powerful.
- Optional start position:
str.indexOf("l", 4), search from index 4 - Backticks
`...`: template literals, support interpolation and multi-line lastIndexOf()finds the last match, useful for file paths and URLsString(42)(nonew) converts a value to a primitive string, this is fine
String Creation
Always use literals. String() for conversion is fine, new String() is not.
Press Run to execute the code and see output here.
Template Literals
Template literals use backticks and unlock two powerful features: embedded expressions via ${} and genuine multi-line strings without escape sequences.
Template Literals
Backtick strings replace concatenation and make multi-line strings natural.
- Embed any expression:
`Total: ${"{price * qty}"}` - Multi-line: press Enter inside backticks, no
\nneeded - Tagged templates: a function can process the template (advanced)
- Nested backticks must be escaped:
\`
Template Literals vs Concatenation
Any valid JavaScript expression goes inside ${}, including ternaries and function calls.
Press Run to execute the code and see output here.
Escape Characters
Escape sequences let you include special characters inside a string that would otherwise be impossible or ambiguous to write directly.
Escape Sequences
A backslash tells the parser to treat the next character specially.
\n: newline\t: tab\\: literal backslash\": double quote inside double-quoted string\': single quote inside single-quoted string\`: backtick inside template literal\u0041: Unicode escape →"A"
Escape Sequences
\\n and \\t are the most common, use template literals to avoid most escaping.
Press Run to execute the code and see output here.
String Properties: length
The length property returns the number of UTF-16 code units in a string. For most characters this equals the number of visible characters, with some exceptions for emoji and surrogate pairs.
.length
The only built-in property on strings, everything else is a method.
- Read-only: you cannot set length to truncate a string
- Empty string
""has length0 - Spaces count:
"hi there".length === 8 - Last character index is always
length - 1
.length Property
length - 1 is always the index of the last character.
Press Run to execute the code and see output here.
charAt() and charCodeAt()
charAt(i) returns the character at index i. charCodeAt(i) returns its UTF-16 numeric code. Both are useful when iterating over characters or doing character-level comparisons.
charAt() / charCodeAt()
Access individual characters by index or get their numeric character codes.
charAt(i): same as bracket notationstr[i]but returns""for out-of-range (bracket givesundefined)charCodeAt(i): UTF-16 code of the character at index iString.fromCharCode(65): reverse: code → character ("A")
charAt and charCodeAt
charCodeAt is useful for sorting algorithms and character-level validation.
Press Run to execute the code and see output here.
concat()
concat() joins two or more strings and returns a new string. In practice, template literals or the + operator are preferred for readability.
concat()
Joins strings, functionally the same as + but more verbose.
- Accepts multiple arguments:
"a".concat("b", "c")→"abc" - Returns a new string, the originals are untouched
- Template literals are almost always cleaner for real use cases
concat()
Prefer template literals over concat, same result, easier to read.
Press Run to execute the code and see output here.
indexOf() and lastIndexOf()
indexOf() returns the index of the first occurrence of a substring. lastIndexOf() searches from the end. Both return -1 if not found.
indexOf() / lastIndexOf()
Find the position of a substring, returns -1 when not found.
- Case-sensitive:
"Hello".indexOf("h")returns-1 - Optional start position:
str.indexOf("l", 4), search from index 4 - Check for existence:
str.indexOf("x") !== -1(or useincludes()) lastIndexOf()finds the last match, useful for file paths and URLs
indexOf and lastIndexOf
Use includes() for a simple existence check, indexOf when you need the position.
Press Run to execute the code and see output here.
slice(), substring(), and substr()
All three extract a portion of a string. slice() is the modern standard, it supports negative indices. substr() is deprecated.
slice() vs substring()
Use slice(), it handles negative indices and is the community standard.
slice(start, end): end is exclusive; negative indices count from the endsubstring(start, end): no negative indices; swaps args if start > endsubstr(start, length): deprecated, second arg is length not end index- None of them mutate the original string
slice vs substring vs substr
slice(-6) counts 6 back from the end, negative indices make slice the clear winner.
Press Run to execute the code and see output here.
toLowerCase() and toUpperCase()
These methods return a new string with all characters converted to lower or upper case. They are commonly used to normalise user input before comparisons.
Case Conversion
Normalise case before comparing strings to avoid case-sensitivity bugs.
- Returns a new string, original is unchanged
- Use for case-insensitive comparisons:
a.toLowerCase() === b.toLowerCase() - Works with all Unicode characters
Case Conversion
Always normalise case before comparing user-provided strings.
Press Run to execute the code and see output here.
trim(), trimStart(), and trimEnd()
These methods remove whitespace (spaces, tabs, newlines) from the edges of a string. Essential for sanitising user input from forms.
trim Methods
Strip leading and/or trailing whitespace, always trim user input before processing.
trim(): removes whitespace from both endstrimStart(): removes from the start (left) onlytrimEnd(): removes from the end (right) only- Does not affect whitespace inside the string
trim, trimStart, trimEnd
Always trim() user input before validation or storage.
Press Run to execute the code and see output here.
split(), replace(), and replaceAll()
split() breaks a string into an array. replace() swaps the first match. replaceAll() swaps every match.
split / replace / replaceAll
The core trio for transforming string content.
split(separator)→ array;split("")splits into individual charactersreplace(search, replacement): replaces only the first matchreplaceAll(search, replacement): replaces all matches- Both replace methods accept regex as the search argument
split, replace, replaceAll
replace only hits the first match, use replaceAll when you want every occurrence.
Press Run to execute the code and see output here.
includes(), startsWith(), and endsWith()
These three ES6 methods return booleans and replace the older indexOf() !== -1 pattern with readable, intent-revealing code.
includes / startsWith / endsWith
Readable boolean checks, prefer these over indexOf for existence testing.
includes(sub): true if sub appears anywherestartsWith(sub): true if string begins with subendsWith(sub): true if string ends with sub- All are case-sensitive; all accept an optional position argument
includes, startsWith, endsWith
url.startsWith('https') reads like plain English, that is the point.
Press Run to execute the code and see output here.
repeat(), padStart(), and padEnd()
repeat() duplicates a string n times. padStart() and padEnd() pad a string to a target length, useful for formatting numbers and IDs.
repeat / padStart / padEnd
Utility methods for generating and formatting string output.
repeat(n): returns the string repeated n timespadStart(length, char): pads from the left until total length is reachedpadEnd(length, char): pads from the right- Default pad character is a space if omitted
repeat, padStart, padEnd
padStart('0') is the standard way to zero-pad numeric IDs and codes.
Press Run to execute the code and see output here.
Multi-line Strings
Template literals make multi-line strings natural, just press Enter. With single or double quotes you must use \n escape sequences or line continuation with a backslash.
Multi-line Strings
Template literals are the clean, modern way to write multi-line string content.
- Template literal: just press Enter inside backticks
- Old way with quotes: append
\nor use string concatenation across lines - Indentation inside the template literal is part of the string
- Useful for HTML snippets, SQL queries, or long messages in code
Multi-line Strings
Template literals preserve actual line breaks, no \\n needed.
Press Run to execute the code and see output here.
String Immutability
Strings are immutable in JavaScript, you cannot change an individual character in place. Every string method returns a new string; the original is never modified.
Immutability
No string method modifies the original, always capture the return value.
- Bracket assignment
str[0] = "X"silently does nothing - Methods like
toUpperCase(),replace(),trim()all return new strings - A common bug: calling a method and not capturing the result
- Immutability makes strings safe to share, no defensive copying needed
String Immutability
The #1 string bug: calling a method and forgetting to save the returned value.
Press Run to execute the code and see output here.
Knowledge Check
1. Which quote style supports multi-line strings and interpolation natively?
2. What does "hello".slice(1, 3) return?
3. What does " hello ".trim() return?
4. Which method checks if a string contains a substring?
5. What is string immutability?
6. What does "abc".padStart(5, "0") return?
7. What does "a,b,c".split(",") return?
8. What escape sequence produces a newline in a string?