Which quotes should you use for text?
A string is a piece of text. You can wrap it in double quotes, single quotes or backticks, and all three make the same kind of value. "rye", 'rye' and ` rye ` are equal.
Pick one style for plain text and stay with it. Many teams use double quotes because text often contains apostrophes: "Today's bake" needs no escaping, while 'Today\'s bake' needs a backslash before the apostrophe. Code formatters such as Prettier will change quotes for you, so do not spend long on it.
Backticks are different in two useful ways. They let you drop values into the text, and they can span several lines without any special characters. Those strings are called template literals.
const bread = "Today's rye";
const note = 'Baked at "6am"';
const both = `Rye and "spelt" aren't sold out`;
console.log(bread, note, both);

slice(start, end) copies from start up to, but without, end, so slice(1, 4) gives three characters.How do template literals put values into text?
Inside backticks, anything you write between ${ and } is run as JavaScript, and the result becomes part of the text. It can be a variable, a sum, a method call or a small ternary.
This replaces long chains of +. Compare "Total: $" + total + " for " + count + " items" with ` Total: $${total} for ${count} items `. The second is easier to read, and you are far less likely to lose a space between words.
The dollar sign in $${total} looks odd. The first $ is ordinary text, a price sign. The second starts the placeholder. If you want a literal ${ in the output, which is rare, put a backslash before the dollar sign.
The most common slip is using ${} inside normal quotes. JavaScript does not complain, it prints the characters ${name} on the page. When you see that, change the quotes to backticks.
const count = 3;
const price = 4.5;
const line = `${count} loaves cost $${count * price}`;
console.log(line);How long is a string, and how do you change its case?
Every string has a length property: the number of characters. It is a property, so there are no brackets: word.length, not word.length(). An empty string has length 0, which makes length handy for checking whether someone typed anything.
Emoji and some accented letters can count as two, because length counts UTF-16 code units. For ordinary letters, digits and spaces it matches what you would count by hand.
toUpperCase() and toLowerCase() return a copy with the case changed. A common use is comparing user input without caring about case: lower both sides first, then compare. "Rye" === "rye" is false, but "Rye".toLowerCase() === "rye" is true.
const typed = "Sourdough";
console.log(typed.length);
console.log(typed.toLowerCase() === "sourdough");Why do string methods never change the original?
Strings in JavaScript are immutable. Once a string exists, nothing can edit its characters. Every method you call on it builds and returns a new string, and the old one stays as it was.
That means a line like name.trim(); on its own does nothing useful. The trimmed copy is created and then dropped because nothing stored it. You need const clean = name.trim();, or you need to use the result directly, as in label.textContent = name.trim();.
Open the Step lens on code like the example below and watch name as each line runs. Its value never changes, even though three methods were called on it. Only shout gets a new value.
This is also why chaining works. name.trim().toUpperCase() calls trim(), gets a new string back, and then calls toUpperCase() on that new string.
const name = " wren ";
name.trim();
name.toUpperCase();
const shout = name.trim().toUpperCase();
console.log(`[${name}]`, `[${shout}]`);How do you clean up and search text?
trim() removes spaces, tabs and line breaks from both ends of a string. Text from form fields often has a stray space at the end, especially on phones that add one after autocomplete, so trim before you compare or store it. trimStart() and trimEnd() clean one side only.
To ask whether text contains something, use includes(). It returns true or false. startsWith() and endsWith() check the beginning and end, which suits file names and codes: file.endsWith(".jpg"), code.startsWith("BK-").
All three are case sensitive. "Sourdough".includes("sour") is false because of the capital S. Lower the text first if case should not matter.
You will see indexOf() in older code. It returns the position of a match or -1 when there is none, so old code wrote if (text.indexOf("rye") !== -1). includes() says the same thing more clearly.
const order = " Rye, Spelt, Sourdough ";
const clean = order.trim().toLowerCase();
console.log(clean.includes("spelt"));
console.log(clean.startsWith("rye"));
console.log(clean.endsWith("loaf"));How do you cut out part of a string?
Characters are numbered from 0. In "SOURDOUGH", S is at index 0 and the final H is at index 8, one less than the length. You can read one character with square brackets, word[0], or with word.at(-1) to count from the end.
slice(start, end) copies the characters from start up to end, without including end. Leave out end to go to the finish. A negative number counts back from the end, so slice(-3) gives the last three characters. The diagram shows slice(1, 4) taking three boxes.
The rule "start included, end left out" means slice(0, n) always returns n characters, which makes short previews easy: text.slice(0, 40) gives the first 40 characters of a review.
Older code uses substring() and occasionally substr(). substring() behaves like slice() for positive numbers; substr() is deprecated. Prefer slice().
const review = "The crust was dark and crackly, the crumb open.";
const preview = review.length > 20 ? `${review.slice(0, 20)}...` : review;
console.log(preview);
console.log(review.slice(-6));How do replace and replaceAll differ?
replace(find, newText) swaps the first match only. replaceAll(find, newText) swaps every match. That difference catches people constantly: replacing dashes in "2026-10-06" with replace changes only the first dash.
replaceAll() has been in every browser since 2020, so you can use it freely. In older code and in some AI answers you will see replace(/-/g, " ") instead. That is a regular expression with the g flag, which means global, and it does the same job.
Both return a new string, as always. The search is case sensitive, and with plain text as the first argument there is nothing special about characters like . or $.
const date = "2026-10-06";
console.log(date.replace("-", "/"));
console.log(date.replaceAll("-", "/"));How do split and join turn text into lists and back?
split(separator) cuts a string at every separator and gives you an array of the pieces. "rye,spelt,oat".split(",") gives ["rye", "spelt", "oat"]. Splitting on " " gives words, and splitting on "" gives single characters.
join(separator) is the array method that goes the other way: it glues the items into one string with the separator between them. Together they let you reshape text: split on one character, join with another.
Watch for spaces. "rye, spelt".split(",") keeps the space before spelt. Trim each piece, or split on ", " if the format is reliable. You will meet map() for trimming every item in the array methods lesson.
const tags = "rye, spelt, oat";
const list = tags.split(", ");
console.log(list.length);
console.log(list.join(" / "));How do you line numbers up with padStart?
padStart(length, padText) adds characters to the front until the string reaches length. It is the usual way to show order numbers like 007 or times like 09:05. padEnd() does the same at the other end, which helps line up columns in console output.
It is a string method, so convert numbers first: String(7).padStart(3, "0"). If the string is already long enough, nothing is added and nothing is cut off.
When you read AI-written string code, look for three things: ${} inside the wrong quotes, a method call whose result is never stored, and replace where every match should change. All three run without an error and give the wrong text, so check the page and the Console instead of trusting that no error means correct.
const hours = 9;
const minutes = 5;
const time = `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
console.log(time);Field notes
- Single quotes, double quotes and backticks all make the same kind of string.
- Inside backticks,
${}puts the result of any expression into the text. - String methods return a new string and leave the original unchanged.
trim()removes stray spaces from both ends, which is common with form input.
Easy to get wrong
String methods return a new string and leave the original alone. Calling one without storing the result throws the work away.
Only backticks fill in ${}. Inside double or single quotes the characters are printed as written.
length is a property holding a number. Adding brackets tries to call that number like a function and throws a TypeError.
replace with plain text changes only the first match. Use replaceAll when every occurrence should change.
Questions people ask
Should I use single quotes, double quotes or backticks?
Any of them make the same string. Use backticks when you insert values or need several lines, and pick one of the other two for plain text. A formatter can enforce the choice so you never think about it.
Can I change one letter inside a string?
No. Strings are immutable, so word[0] = "B" is silently ignored. Build a new string instead, for example "B" + word.slice(1).
How do I compare text without caring about capitals?
Lower both sides first: a.toLowerCase() === b.toLowerCase(). For sorting names in a real language, localeCompare handles accents and is the better tool.
Why does my string have a space at the end?
Text from inputs, pasted values and phone keyboards often carries a trailing space. Call trim() before comparing or saving, and wrap the value in brackets when you log it, like [${value}], so the space is visible.
Is a number in quotes a number?
No. "4.50" is text. Adding to it joins text, so "4.50" + 1 gives "4.501". Convert with Number() before doing maths, as the types lesson explains.