Why Text Matters in Every App
Meena runs Annapurna Tiffin Service from her kitchen in Pune. Every morning about forty office workers order lunch through her small web app, and every order needs a message: “Hello Priya! Order TIF-007 is packed. Total: Rs. 185.”
The problem is that customers type their details in every possible way. One person types " priya NAIR " with extra spaces and capital letters. Another writes the order items as one long line with commas. Meena wants clean, friendly messages without fixing each one by hand.
All of this is text, and in JavaScript text is called a string. In this lesson you will learn how to create strings, join them, search inside them, cut them, clean them and format them. By the end you will build Meena’s order message yourself.
You met strings briefly in the Data Types lesson. Here we go much deeper and learn the methods (built-in tools) that every JavaScript developer uses daily.
Creating Strings: Three Kinds of Quotes
A string is any text inside quotes. JavaScript accepts three kinds of quotes:
| Quotes | Example | When to use |
|---|---|---|
Single ' ' | 'Rajma Chawal' | Simple text |
Double " " | "Today's special" | Simple text, or text with an apostrophe |
Backticks ` ` | `Hi ${name}` | Text that includes variables or spans many lines |
Single and double quotes work the same way. Just start and end with the same kind. If your text contains an apostrophe, wrap it in double quotes, or put a backslash (\) before the apostrophe. The backslash tells JavaScript: “this quote is part of the text, not the end of the string.” This is called escaping.
// Three ways to write a string
const service = 'Annapurna Tiffin Service';
const dish = "Rajma Chawal";
const note = `Less spicy, please`;
// Use double quotes when the text has an apostrophe
const special = "Today's special";
// Or "escape" the apostrophe with a backslash
const sameSpecial = 'Today\'s special';
console.log(service); // Annapurna Tiffin Service
console.log(special); // Today's special
console.log(sameSpecial); // Today's special
The backtick key is usually at the top left of the keyboard, next to 1, under Esc.
Template Literals: Putting Values Inside Text
A string written with backticks is called a template literal. Inside it, you can write ${...} and put any variable or calculation between the curly braces. JavaScript replaces it with the value. Think of it as a form with blanks that JavaScript fills in for you.
const customer = "Kavya";
const thalis = 2;
const price = 120;
// Old way: joining pieces with +
const oldMessage = "Hi " + customer + ", your " + thalis + " thalis cost Rs. " + (thalis * price) + ".";
// Template literal: backticks and ${...}
const newMessage = `Hi ${customer}, your ${thalis} thalis cost Rs. ${thalis * price}.`;
console.log(oldMessage); // Hi Kavya, your 2 thalis cost Rs. 240.
console.log(newMessage); // Hi Kavya, your 2 thalis cost Rs. 240.
// Template literals can also span many lines
const menu = `Today's menu:
Dal Tadka
Jeera Rice`;
console.log(menu);
Both lines print the same message, but the template literal is much easier to read and has fewer chances of a missing space or a missing +. Most modern code uses template literals whenever a string contains values.
Length and Indexing: Counting and Picking Characters
Every string knows how many characters it has. Read it with .length (no brackets, because it is a property, not a method). Spaces and punctuation count as characters too.
Each character also has a position number, called an index. Counting starts at 0, not 1. So in "Kothrud", K is at index 0 and the last letter d is at index 6, which is length - 1.
const area = "Kothrud";
console.log(area.length); // 7
console.log(area[0]); // K (the first character)
console.log(area[3]); // h
console.log(area[area.length - 1]); // d (the last character)
console.log(area.at(-1)); // d (at() counts from the end with a minus number)
console.log(area[20]); // undefined (there is no character at position 20)
Cleaning Text: Changing Case and Trimming Spaces
This is where Meena’s messy names get fixed. A method is an action a string can do, and you call it with a dot and round brackets, like name.trim().
| Method | What it returns |
|---|---|
trim() | The text without spaces at the start and the end |
trimStart() / trimEnd() | Spaces removed from one side only |
toUpperCase() | All capital letters |
toLowerCase() | All small letters |
// The customer typed their name with extra spaces and mixed capitals
const typedName = " rAHUL sharma ";
const clean = typedName.trim();
console.log(clean); // rAHUL sharma
console.log(clean.toUpperCase()); // RAHUL SHARMA
console.log(clean.toLowerCase()); // rahul sharma
// trimStart and trimEnd remove spaces from only one side
console.log(`[${typedName.trimStart()}]`); // [rAHUL sharma ]
console.log(`[${typedName.trimEnd()}]`); // [ rAHUL sharma]
// The original string has not changed
console.log(`[${typedName}]`); // [ rAHUL sharma ]
Notice the square brackets in the output. They show exactly where the spaces are. This is a useful trick when you are not sure if a string has hidden spaces.
Searching Inside a String
Customers write notes like “No onion, extra roti”. The kitchen needs to know quickly if a note mentions onion. These methods help:
includes(text)returnstrueif the text appears anywhere.startsWith(text)andendsWith(text)check only the beginning or the end.indexOf(text)returns the index where the text starts, or-1if it is not found.
const note = "No onion, extra roti, deliver to Gate 2";
console.log(note.includes("onion")); // true
console.log(note.includes("Onion")); // false (capital O is different)
console.log(note.toLowerCase().includes("onion")); // true
console.log(note.startsWith("No")); // true
console.log(note.endsWith("Gate 2")); // true
console.log(note.indexOf("roti")); // 16 (position where "roti" starts)
console.log(note.indexOf("paneer")); // -1 (not found)
All searches are case sensitive: "Onion" and "onion" are different. A common habit is to change both sides to lower case before searching, as the third line shows.
Cutting and Replacing: slice, replace and replaceAll
slice(start, end) copies a part of the string. It starts at the start index and stops just before the end index. Leave out end to go to the last character. A negative number counts from the end, so slice(-4) gives the last four characters.
replace(old, new) swaps the first match only. replaceAll(old, new) swaps every match. Imagine Meena runs out of potatoes and wants to switch every dish to paneer:
const orderCode = "PUNE-LUNCH-0425";
// slice(start, end): from start up to, but not including, end
console.log(orderCode.slice(0, 4)); // PUNE
console.log(orderCode.slice(5, 10)); // LUNCH
console.log(orderCode.slice(-4)); // 0425 (the last 4 characters)
const menu = "Aloo Gobi, Aloo Matar, Aloo Paratha";
// replace changes only the FIRST match
console.log(menu.replace("Aloo", "Paneer"));
// Paneer Gobi, Aloo Matar, Aloo Paratha
// replaceAll changes EVERY match
console.log(menu.replaceAll("Aloo", "Paneer"));
// Paneer Gobi, Paneer Matar, Paneer Paratha
split, join and padStart
split(separator) cuts a string into pieces wherever it finds the separator and gives you a list of the pieces. This list is called an array. You will study arrays properly in the Arrays lesson; for now, just think of it as a numbered list. join(separator) does the opposite: it glues a list back into one string.
padStart(length, character) adds characters at the start until the string reaches the length you asked for. It is perfect for order numbers like 007. Numbers do not have padStart, so first turn the number into a string with String(...).
// split: cut a string into a list (an array)
const items = "Roti,Dal,Rice,Salad";
const itemList = items.split(",");
console.log(itemList); // ["Roti", "Dal", "Rice", "Salad"]
console.log(itemList.length); // 4
// join: glue the list back into one string
console.log(itemList.join(" + ")); // Roti + Dal + Rice + Salad
// padStart: add characters at the start until the string is long enough
const orderNumber = 7;
console.log(String(orderNumber).padStart(3, "0")); // 007
console.log(String(42).padStart(3, "0")); // 042
console.log(String(1250).padStart(3, "0")); // 1250 (already long enough)
There is also padEnd(), which adds characters at the end. It is handy for lining up text in columns.
Strings Cannot Be Changed (They Are Immutable)
This is one of the most important ideas in this lesson. Once a string is created, it can never be changed. We say strings are immutable. Every method you learned today leaves the original string exactly as it was and gives you back a new string. If you want to keep the new string, you must store it in a variable.
let city = "pune";
// You cannot change one character inside a string
city[0] = "P";
console.log(city); // pune (nothing changed)
// String methods never change the original. They RETURN a new string.
city.toUpperCase();
console.log(city); // pune (the new string was thrown away)
// Save the result to keep it
city = city[0].toUpperCase() + city.slice(1);
console.log(city); // Pune
The line city[0] = "P" is silently ignored here. In strict mode (which you will meet later, inside modules and classes) the same line throws a TypeError instead. Either way, the string does not change.
The last line shows a pattern you will use often: take the first character, make it a capital, and join it with the rest of the string from slice(1).
Real-Life Example: Meena’s Order Message
Now let us put everything together. The customer typed their details carelessly. Our code cleans the name, builds a neat order code and prepares the final message. Run it and read each step.
// Data typed by the customer in the order form
const rawName = " priya NAIR ";
const orderNo = 7;
const rawItems = "veg thali, curd, gulab jamun";
const total = 185;
// 1. Clean the name: remove spaces, then fix the capital letters
const name = rawName.trim().toLowerCase();
const firstName = name.split(" ")[0];
const niceFirst = firstName[0].toUpperCase() + firstName.slice(1);
// 2. Order number with 3 digits
const orderCode = "TIF-" + String(orderNo).padStart(3, "0");
// 3. Items: split on commas and join with a bullet
const itemText = rawItems.split(", ").join(" | ");
// 4. Build the final message with a template literal
const message = `Hello ${niceFirst}! Order ${orderCode} is packed.
Items: ${itemText}
Total: Rs. ${total}. Thank you for choosing Annapurna Tiffin.`;
console.log(message);
// Hello Priya! Order TIF-007 is packed.
// Items: veg thali | curd | gulab jamun
// Total: Rs. 185. Thank you for choosing Annapurna Tiffin.
console.log(message.includes("TIF-007")); // true
Try these changes:
- Change
orderNoto48and check that the code becomesTIF-048. - Show the items in capital letters by adding
.toUpperCase()in the right place. - Change
rawNameto" MOHAN das"and confirm the message still says “Hello Mohan!”.
Common Mistakes
- Using normal quotes with
${...}. The value is only filled in inside backticks. In normal quotes, you get the dollar sign and braces printed as plain text.
const customer = "Arjun";
// Wrong: ${...} inside normal quotes is just plain text
console.log("Hi ${customer}"); // Hi ${customer}
// Right: use backticks
console.log(`Hi ${customer}`); // Hi Arjun
- Expecting a method to change the original. Writing
name.trim();on its own line does nothing useful. Writename = name.trim();(withlet) or store it in a newconst. - Writing
length()with brackets.lengthis a property, not a method, so it has no brackets. With brackets you get an error:
const dish = "Poha";
console.log(dish.length); // 4
console.log(dish.length()); // ERROR: TypeError, dish.length is not a function
- Forgetting that counting starts at 0. The last character is at
length - 1, not atlength. - Using
replacewhen you want every match changed.replacechanges only the first one. UsereplaceAll.
Practice Task: A South Indian Breakfast Order
Meena has started a breakfast menu. Write code that turns this messy order into a clean message. Your code should:
- Clean the name so it becomes
Anand kumar - Create the order code
TIF-0052usingpadStart - Turn
"Idli;Vada;Sambar;Chutney"into"Idli, Vada, Sambar, Chutney" - Print one full message using a template literal
- Print whether the items include
"Vada"
const rawName = " ANAND kumar ";
const orderNo = 52;
const rawItems = "Idli;Vada;Sambar;Chutney";
const total = 140;
// TODO 1: Trim rawName and change it to lower case, then make the first letter capital
// TODO 2: Make an order code like "TIF-0052" (4 digits)
// TODO 3: Split rawItems on ";" and join the items with ", "
// TODO 4: Build the message with a template literal and print it
// TODO 5: Print true or false: does the item list include "Vada"?
Show one possible answer (try it yourself first!)
const rawName = " ANAND kumar ";
const orderNo = 52;
const rawItems = "Idli;Vada;Sambar;Chutney";
const total = 140;
const lower = rawName.trim().toLowerCase();
const name = lower[0].toUpperCase() + lower.slice(1);
console.log(name); // Anand kumar
const orderCode = `TIF-${String(orderNo).padStart(4, "0")}`;
console.log(orderCode); // TIF-0052
const itemText = rawItems.split(";").join(", ");
console.log(itemText); // Idli, Vada, Sambar, Chutney
const message = `Dear ${name}, your order ${orderCode} (${itemText}) costs Rs. ${total}.`;
console.log(message);
// Dear Anand kumar, your order TIF-0052 (Idli, Vada, Sambar, Chutney) costs Rs. 140.
console.log(rawItems.includes("Vada")); // true
Key Takeaways
- Strings can use single quotes, double quotes or backticks. Backticks make template literals, which fill in
${...}with values. lengthgives the number of characters, and indexes start at 0.trim,toUpperCaseandtoLowerCaseclean up text typed by users.includes,startsWith,endsWithandindexOfsearch inside text, and they are case sensitive.slice,replace,replaceAll,split,joinandpadStartcut, change and format text.- Strings are immutable: methods return a new string, so save the result in a variable.