Three Ways to Write a String
JavaScript gives you three string delimiters. Two of them are interchangeable; the third does more.
Single and double quotes produce identical strings — pick one and stick with it (most modern codebases default to single quotes or let a formatter decide). Backticks produce a template literal, which is where things get interesting: they allow interpolation and span multiple lines.
Under the hood all three produce the same primitive string type. The delimiter is just a syntactic choice.
Escape Sequences and Embedded Quotes
Inside a string, a backslash starts an escape sequence. The common ones are \n (newline), \t (tab), \\ (literal backslash), and \" / \' for embedding the same quote you opened with:
You can avoid most escapes by picking the other quote style: 'She said "hi" and left.' needs no backslashes. Pragmatic over dogmatic.
Template Literals: the Backtick Superpower
A template literal does two things plain strings can't. First, it interpolates expressions with ${...}:
Anything inside ${...} is a JavaScript expression, not just a variable name. Arithmetic, function calls, ternaries, even other template literals — all fair game:
Second, template literals span multiple lines without needing \n:
Newlines in the source become newlines in the string. For anything longer than a short label, backticks are almost always the right call.
Interpolation Beats Concatenation
Before template literals, the only way to build a dynamic string was the + operator:
Both produce identical output. The template literal reads like the sentence it's building, while the + version forces you to track quotes, spaces, and concatenation operators. Use + only when you're appending one small thing to an existing string. For anything longer, reach for backticks.
Strings Are Immutable
Every method that looks like it modifies a string actually returns a new one:
If you want the change, you have to assign the result somewhere. This bites beginners who write s.replace("a", "b") and expect s to change. It doesn't. Strings in JavaScript are like numbers: the value itself can't be mutated, only the variable can be pointed at a new value.
The String Methods You'll Actually Use
The full string API is large. The handful you'll reach for daily:
A few notes worth memorising:
lengthis a property, not a method — no parentheses.replacewith a plain string replaces only the first match. UsereplaceAllor a regex with thegflag to replace all occurrences.slice(start, end)takes a half-open range: the character atendis not included.- Negative indices on
slicecount from the end:s.slice(-3)gives the last three characters.
Indexing and Iterating Characters
Strings behave like read-only arrays of characters. You can index them and iterate them, but you can't assign to a position:
for...of iterates code points, which handles most Unicode correctly. Using indices (s[i]) iterates UTF-16 code units, which can split emoji and other non-BMP characters in half. For ordinary text, both are fine; for anything user-generated, prefer for...of or [...s].
Tagged Template Literals
There's one more form worth knowing about, even if you don't write them often. A tagged template literal calls a function with the static string pieces and the interpolated values as separate arguments:
The tag function decides what the final string looks like — it can escape HTML, build SQL safely, compile CSS, or parse GraphQL. You'll see this pattern in libraries (styled-components, graphql-tag, lit-html) far more often than you'll write one yourself. But when you do need custom string processing, tags are the cleanest tool for the job.
Common Pitfalls
A short list of things that trip people up:
- Forgetting to assign method results.
s.trim()does nothing on its own. - Using
+to concatenate a number and a string."Age: " + 30 + 5is"Age: 305", not"Age: 35". Template literals sidestep this:`Age: ${30 + 5}`. - Mixing up
==and string comparison. We'll cover equality properly later, but"1" == 1istrueand"1" === 1isfalse. Prefer===. - Assuming
lengthequals character count. For emoji and other surrogate-pair characters,"".lengthis 2, not 1. Use[..."".length]orArray.from(s).lengthwhen you need user-perceived characters.
Next: Numbers and BigInt
Strings are one primitive type; numbers are another, and JavaScript's number system has its own quirks — a single Number type for both integers and floats, plus BigInt for when that's not enough. That's the next page.
Frequently Asked Questions
What's the difference between quotes and backticks in JavaScript?
Single (') and double (") quotes both create plain strings — they're interchangeable. Backticks (`) create template literals, which support interpolation with ${...} and span multiple lines without escape characters. Reach for backticks whenever you're inserting a variable or writing text across several lines.
How do you insert a variable into a string in JavaScript?
Use a template literal: wrap the string in backticks and put the expression inside ${...}. For example, `Hello, ${name}!` evaluates name and splices the result in. You can put any expression inside — ${a + b}, ${user.name.toUpperCase()}, even nested template literals.
Are JavaScript strings immutable?
Yes. Every string method (toUpperCase, slice, replace, and so on) returns a new string rather than modifying the original. If you write s.toUpperCase() and don't assign the result to anything, nothing changes. This is the same model as strings in Python or Java.
What are tagged template literals?
A tagged template literal calls a function with the template's string pieces and interpolated values as separate arguments: tag`Hello, ${name}` invokes tag(["Hello, ", ""], name). Libraries like styled-components and graphql-tag use tags to parse or transform the template before producing the final value.