Skip to content
JavaScript js strings 5 min read

String Basics

A string is JavaScript’s type for text — a sequence of characters used for everything from user names and URLs to JSON payloads and HTML markup. Strings feel simple, but a few core facts shape how you work with them every day: they can be written with three different kinds of quotes, they are immutable, and each character lives at a zero-based index. This page covers creating strings, reading their length and individual characters, escaping special characters, and joining strings together.

Creating strings

You can write a string literal with single quotes, double quotes, or backticks (template literals). All three produce the same string primitive — the choice is mostly about which quote characters you need to embed without escaping.

const single = 'hello';
const double = "hello";
const backtick = `hello`;

console.log(single === double, double === backtick);

Output:

true true

Single and double quotes are interchangeable; pick one and stay consistent (most style guides and formatters default to one or the other). Backticks unlock interpolation and multi-line text, which are covered in detail on the template literals page.

Quote styleMulti-lineInterpolationTypical use
'single'NoNoDefault for plain text
"double"NoNoWhen the text contains apostrophes
`backtick`YesYes (${})Dynamic or multi-line strings

You can also wrap any value with the String() function to convert it to text. Avoid new String() — that creates a wrapper object, not a primitive, and behaves surprisingly with typeof and ===.

console.log(String(42));        // "42"
console.log(typeof String(42)); // "string"
console.log(typeof new String("x")); // "object"  ← avoid

Immutability

Strings are immutable: once created, the characters inside a string can never be changed. Methods like toUpperCase(), slice(), or replace() do not modify the original — they return a brand-new string. Assigning to an index simply does nothing (it throws in strict mode for some hosts, but is silently ignored otherwise).

let greeting = "hello";

greeting[0] = "H";        // ignored — strings are immutable
console.log(greeting);    // still "hello"

greeting = greeting.toUpperCase(); // reassign the variable
console.log(greeting);    // "HELLO"

Output:

hello
HELLO

The variable can be reassigned, but the string value itself never mutates. To “edit” a string you build a new one and store it back. This is why chaining string methods is safe — each call hands you a fresh string.

Length

Every string has a read-only length property reporting the number of UTF-16 code units it contains. For plain ASCII and most everyday text, that equals the number of characters you see.

console.log("hello".length); // 5
console.log("".length);      // 0
console.log("  ".length);    // 2 (spaces count)

Output:

5
0
2

length counts code units, not always visual characters. Emoji and other characters above the basic plane take two code units, so "😀".length is 2. See the Unicode strings page when you need true character counts.

Accessing characters

There is no dedicated character type in JavaScript — a single character is just a string of length 1. You read characters by zero-based index using either bracket notation or the at() method.

const word = "code";

console.log(word[0]);       // "c"
console.log(word.charAt(1)); // "o"
console.log(word.at(-1));    // "e"  ← ES2022, counts from the end
console.log(word[99]);       // undefined (out of range)

Output:

c
o
e
undefined

Bracket notation does not accept negative indexes (word[-1] is undefined), so reach for at(-1) to grab the last character. charAt() is the older equivalent of bracket access and returns an empty string "" for out-of-range indexes instead of undefined.

Escape sequences

Inside quoted strings, a backslash (\) starts an escape sequence that represents a character you can’t type directly — a newline, a tab, or the same quote that delimits the string.

const quote = 'She said "it\'s fine"';
const lines = "line one\nline two";
const tabbed = "name:\tValue";
const path = "C:\\Users\\dev";

console.log(quote);
console.log(lines);
console.log(tabbed);
console.log(path);

Output:

She said "it's fine"
line one
line two
name:	Value
C:\Users\dev

Common escapes:

SequenceMeaning
\nNewline
\tTab
\\Literal backslash
\' \"Quote matching the delimiter
\u{1F600}Unicode code point (ES2015)
\` ${Backtick / interpolation inside template literals

Concatenation

The classic way to join strings is the + operator. When either operand is a string, + coerces the other to a string and concatenates.

const first = "Ada";
const last = "Lovelace";

const full = first + " " + last;
console.log(full);
console.log("Score: " + 100); // number coerced to "100"

Output:

Ada Lovelace
Score: 100

For anything beyond trivial joins, template literals are clearer than a chain of + signs — they read like the final string and handle interpolation, multi-line text, and embedded expressions without escaping. You can also use concat() or Array.prototype.join() when assembling many pieces.

const items = ["a", "b", "c"];
console.log(items.join(", ")); // "a, b, c"
console.log("foo".concat("bar")); // "foobar"

Best Practices

  • Pick one quote style for plain strings and let your formatter enforce it.
  • Reach for template literals over + whenever you interpolate values or span multiple lines.
  • Remember strings are immutable — capture the return value of methods; they never edit in place.
  • Use at(-1) for the last character; bracket notation can’t take negative indexes.
  • Treat length as code units, not always visual characters, when handling emoji or non-BMP text.
  • Avoid new String(); use the String() function or a literal to get a real string primitive.
  • Escape only what you must — switching quote style often removes the need for \' or \".
Last updated June 1, 2026
Was this helpful?