Computer Programming 1 (JavaScript) • Strings & Text Processing

Text Processing Programs — I can build a small text-processing program that produces a clear, formatted output.

Learn to transform raw text into polished, structured output using JavaScript string methods and formatting techniques.

A JavaScript data file with code brackets and a laptop.
Inside this lesson 10 sections 5 questions 5 figures

SECTION 1

Historical Context & Motivation

Every time you send a text message, search a website, or fill out an online form, a program is processing text behind the scenes. Text processing — the act of reading, transforming, and formatting strings of characters — is one of the oldest and most essential tasks in computing. Before graphical user interfaces existed, the only way humans communicated with computers was through text, so the need for programs that could parse and reformat textual data emerged right alongside the first programming languages.

Understanding this history helps explain why JavaScript ships with such a rich set of string methods. Each new era of computing added fresh demands — from formatting military reports to rendering dynamic web pages — and programmers responded by building more powerful text-processing tools.

1950s • Early Text Processing

Early computers like the UNIVAC processed text for census data and military communications. Programmers manipulated strings character by character using machine code, a tedious but groundbreaking advance.

1970s • Unix & Pipes

The Unix operating system introduced small, composable text-processing utilities like grep, sed, and awk. These tools could be chained together to transform text in powerful ways.

1987 • Perl & Regex

Larry Wall created Perl, a language built specifically for text processing. It popularized regular expressions, making complex pattern matching accessible to everyday programmers.

1995 • JavaScript Is Born

Brendan Eich created JavaScript in just 10 days for the Netscape browser. Built-in string methods like substring() and indexOf() made text processing possible right inside the web browser.

2015+ • Modern JS & Template Literals

ES6 introduced template literals with backticks, making formatted text output dramatically easier. Methods like padStart() and includes() further enriched JavaScript's text-processing toolkit.

Today's challenge is the same one programmers have faced for decades: given messy or unstructured text, how do you write a program that cleans it up, extracts the parts you need, and presents a clear, formatted output? That is exactly what you will learn in this lesson.

SECTION 2

Core Principles of Text Processing

Before you start writing code, it helps to understand the fundamental ideas that every text-processing program relies on. Whether you are building a receipt formatter, a username validator, or a search tool, these four principles remain constant.

1

Input → Transform → Output

Every text-processing program follows a three-stage pipeline. You accept input (a raw string), transform it using string methods, and produce output that is clean and readable.
2

Strings Are Immutable

In JavaScript, strings cannot be changed in place. Every method like .toUpperCase() or .slice() returns a new string. The original stays untouched.
3

Method Chaining

Because each string method returns a new string, you can chain calls together, like str.trim().toLowerCase().replace('a','b'). This keeps your code concise and readable.
4

Template Literals for Output

Template literals use backticks (`) and ${expression} placeholders to embed variables directly into a string. They make formatted output far easier to read than string concatenation with +.
✦

KEY TAKEAWAY

Think of text processing like an assembly line in a factory. Raw materials (the input string) enter at one end, machines (string methods) shape and polish them at each station, and a finished product (the formatted output) comes out the other end. You never modify the raw material itself — you always create a new, improved version at each step.

SECTION 3

The Text-Processing Pipeline

The diagram below illustrates the core pipeline that every text-processing program follows. Notice how the raw input string passes through multiple transformation stages before arriving at the final formatted output. Each stage uses one or more JavaScript string methods, and the data flows in a single direction from left to right.

Text-Processing PipelineData flows from INPUT → TRANSFORM → OUTPUT1. INPUT" Jane DOE "(raw user input)2. TRIM.trim()→ "Jane DOE"3. CASE.toLowerCase()→ "jane doe"4. FORMATcapitalize each word→ "Jane Doe"5. OUTPUT"Welcome, Jane Doe!"(template literal)Key String Methods Used.trim() .toLowerCase() .toUpperCase().slice() .split() .join() .replace().padStart() .padEnd() .includes()
The pipeline starts with raw input (stage 1), removes whitespace with .trim() (stage 2), normalizes case (stage 3), applies custom formatting (stage 4), and embeds the result in a template literal for final output (stage 5).

Notice how the string value changes at every stage but the original input is never altered. This is immutability in action — each method produces a brand-new string, which flows into the next stage. When you chain methods together in your code, you are essentially compressing this entire pipeline into a single readable expression.

SECTION 4

How String Methods Work

JavaScript provides a generous toolkit of built-in string methods. Rather than memorizing every one, focus on understanding the categories they fall into and how they combine. Below are the most important methods you will use in text-processing programs, grouped by purpose.

Cleaning Methods

The .trim() method removes whitespace from both ends of a string. Its cousins, .trimStart() and .trimEnd(), remove whitespace from only one end. Cleaning input is almost always your first step, because users frequently add accidental spaces when typing.

Case Conversion Methods

.toUpperCase() converts every character to uppercase, and .toLowerCase() does the opposite. These are critical for normalizing text so that comparisons work reliably. For example, "Apple", "APPLE", and "apple" are different strings in JavaScript, but after calling .toLowerCase() on all of them, they become identical.

Extraction Methods

.slice(start, end) extracts a portion of a string by index. The start index is inclusive and the end index is exclusive. If you want to grab just the first character for capitalization, you would write str.slice(0, 1). Meanwhile, .split(separator) breaks a string into an array of substrings. For instance, "a,b,c".split(",") returns ["a", "b", "c"].

Replacement & Search Methods

.replace(search, replacement) swaps the first occurrence of a substring, while .replaceAll(search, replacement) swaps every occurrence. The .includes() method returns true or false depending on whether a substring exists within the string — perfect for conditional logic in your programs.

Padding & Joining Methods

.padStart(targetLength, padString) and .padEnd(targetLength, padString) add characters to the beginning or end of a string until it reaches a desired length. These are fantastic for creating aligned, table-like output in the console. The .join(separator) method is actually an array method, but it is the natural partner to .split(): it merges an array of strings back into one string with the separator between each element.

💡

Template Literal Syntax

Template literals are enclosed in backticks (`) instead of quotes. Inside the backticks, you can embed any JavaScript expression using ${expression}. For example: `Hello, ${name}! You are ${age} years old.` Template literals also support multi-line strings without needing \n escape characters.

SECTION 5

String Methods at a Glance

The following table summarizes the most commonly used string methods you will need for text-processing programs. Keep this as a quick reference while you code.

MethodWhat It DoesExampleReturns
.trim()Removes whitespace from both ends" hi ".trim()"hi"
.toUpperCase()Converts all characters to uppercase"hello".toUpperCase()"HELLO"
.toLowerCase()Converts all characters to lowercase"HI".toLowerCase()"hi"
.slice(start, end)Extracts part of a string by index"abcde".slice(1, 3)"bc"
.split(sep)Splits string into an array"a-b-c".split("-")["a","b","c"]
.join(sep)Joins array elements into a string["a","b"].join(", ")"a, b"
.replace(a, b)Replaces first match of a with b"foo foo".replace("foo","bar")"bar foo"
.replaceAll(a, b)Replaces every match of a with b"foo foo".replaceAll("foo","bar")"bar bar"
.includes(sub)Checks if substring exists"hello".includes("ell")true
.padStart(n, ch)Pads start to reach length n"5".padStart(3, "0")"005"

Essential JavaScript string methods for text processing

Method Chaining — Step by StepEach method returns a new string, which feeds into the next methodORIGINAL INPUTlet raw = " jOHn sMITh ";STEP 1: .trim()"jOHn sMITh"removes leading/trailing spacesSTEP 2: .toLowerCase()"john smith"normalizes caseSTEP 3: .split(" ") → capitalize each → .join(" ")"John Smith"splits, transforms, rejoinsFINAL OUTPUT (template literal)`Name: ${formatted}` → "Name: John Smith"
This diagram traces a messy input string through four stages of method chaining. The original string " jOHn sMITh " is cleaned, normalized, and title-cased before being embedded in a template literal for final output.

The key insight from this diagram is that split and join form a powerful pair. When you need to apply a transformation to each word in a sentence, you split the string into an array of words, transform each element (for example, capitalizing the first letter), and then join the array back into a single string. This split-transform-join pattern appears in nearly every text-processing program you will write.

SECTION 6

Worked Example: Building a Receipt Formatter

Let's build a small program that takes product data and produces a neatly formatted receipt. This example uses every principle from the lesson: cleaning input, transforming case, padding for alignment, and outputting with template literals.

Receipt Formatter Program

  1. 1

    Step 1 — Define the Input Data

    We start with an array of product objects. Each object has a name (which may be messy) and a price (a number). Our input looks like this:
    const items = [ { name: " COFFEE mug ", price: 12.5 }, { name: "notebook", price: 7 }, { name: " PEN set", price: 15.99 } ];
  2. 2

    Step 2 — Write a Title Case Function

    We need a helper function that converts any string to title case. We split the string by spaces, capitalize the first letter of each word using .slice() and .toUpperCase(), then join the words back together.
    function titleCase(str) { return str .trim() .toLowerCase() .split(" ") .filter(word => word.length > 0) .map(word => word[0].toUpperCase() + word.slice(1)) .join(" "); }
  3. 3

    Step 3 — Format Each Line with Padding

    To make the receipt look like a table, we use .padEnd() on the product name so every name column is the same width, and .padStart() on the price so dollar amounts align to the right. We also use .toFixed(2) to ensure every price has two decimal places.
    function formatLine(item) { const name = titleCase(item.name).padEnd(20, "."); const price = item.price.toFixed(2).padStart(8); return `${name} $${price}`; }
  4. 4

    Step 4 — Calculate the Total

    We use .reduce() on the items array to sum all prices. This gives us a single number we can format with .toFixed(2).
    const total = items .reduce((sum, item) => sum + item.price, 0) .toFixed(2);
  5. 5

    Step 5 — Build and Print the Receipt

    Finally, we assemble the full receipt using a template literal with multi-line formatting. We map each item to a formatted line and join them with newline characters.
    const receipt = ` ========== RECEIPT ========== ${items.map(formatLine).join("\n")} ----------------------------- $("TOTAL".padEnd(20)) $${total.padStart(8)} ============================= `; console.log(receipt);
  6. 6

    Step 6 — View the Output

    When you run the program, the console displays a clean, aligned receipt. Every product name is title-cased, dot-padded, and the prices line up on the right.
    ========== RECEIPT ========== Coffee Mug............ $ 12.50 Notebook.............. $ 7.00 Pen Set............... $ 15.99 ----------------------------- TOTAL $ 35.49 =============================

SECTION 7

Concatenation vs. Template Literals

You may have seen code that builds strings using the + operator, known as string concatenation. While this approach works, modern JavaScript offers template literals as a more readable and powerful alternative. Understanding the differences will help you choose the right tool for the job.

FeatureConcatenation (+)Template Literals (`)
Syntax"Hi, " + name + "!"`Hi, ${name}!`
Multi-line stringsRequires \n escape charactersSupports natural line breaks inside backticks
Expressions inside stringsMust close quotes, add +, write expression, add + againEmbed directly with ${}
ReadabilityGets messy with many variablesReads almost like natural language
Best forSimple two-part joinsComplex, formatted output

Comparison of string concatenation and template literals in JavaScript

✦

KEY TAKEAWAY

Think of string concatenation like writing a letter and stopping to glue in a photograph every few words — it works, but it is clunky. Template literals are like a mail-merge template where you leave labeled blanks and the computer fills them in automatically. For any output more complex than joining two short pieces, template literals will save you time and make your code much easier to read and debug.

SECTION 8

From String Methods to Regular Expressions

The string methods you have learned so far are powerful, but they have limits. What if you need to find all phone numbers in a block of text, or validate that an email address follows the correct format? These tasks require pattern matching, which is where regular expressions (regex) come in. Regular expressions are a specialized mini-language for describing text patterns, and JavaScript has built-in support for them.

CapabilityString Methods (This Lesson)Regular Expressions (Future)
Find exact substring✅ .includes(), .indexOf()✅ .match()
Find a pattern (e.g., any digit)❌ Not supported✅ /\d+/
Replace all matches✅ .replaceAll()✅ .replace(/pattern/g, ...)
Validate format (email, phone)⚠️ Requires manual logic✅ /^[\w.]+@[\w.]+$/.test()
Learning curveLow — intuitive method namesModerate — cryptic syntax at first

String methods vs. regular expressions: capabilities comparison

For now, you should feel confident that the string methods covered in this lesson can handle the vast majority of text-processing tasks you will encounter. When you are ready, regular expressions will extend your abilities into pattern-based text processing — finding, validating, and replacing text based on flexible rules rather than exact matches. Think of string methods as your everyday toolkit and regex as the power tools you bring out for specialized jobs.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Explain why JavaScript strings are called "immutable." If strings cannot be changed, how do methods like .toUpperCase() seem to modify them?
Show answer
Immutable means that once a string is created, its characters cannot be altered in place. When you call .toUpperCase() on a string, the method does not change the original string. Instead, it creates and returns a brand-new string with all uppercase characters. The original variable still holds the old value unless you explicitly reassign it, like str = str.toUpperCase();. This behavior is why method chaining works: each method in the chain receives the new string produced by the previous method.

Question 2: BASIC CALCULATION

What is the output of the following code? let msg = " Hello, World! "; let result = msg.trim().toLowerCase().replace("hello", "goodbye"); console.log(result);
Show answer
The output is "goodbye, world!". Here is the chain traced step by step: .trim() removes the leading and trailing spaces, giving "Hello, World!". Then .toLowerCase() converts every character to lowercase, producing "hello, world!". Finally, .replace("hello", "goodbye") swaps the first occurrence of "hello" with "goodbye", resulting in "goodbye, world!".

Question 3: INTERMEDIATE

Write a function called formatPhoneNumber that takes a 10-digit string like "5551234567" and returns it in the format "(555) 123-4567". Use .slice() and template literals.
Show answer
Here is one solution: function formatPhoneNumber(digits) { const area = digits.slice(0, 3); const prefix = digits.slice(3, 6); const line = digits.slice(6); return `(${area}) ${prefix}-${line}`; } The function uses .slice() three times to extract the area code (indices 0–2), the prefix (indices 3–5), and the line number (indices 6–9). These three pieces are then assembled into the desired format using a template literal. Calling formatPhoneNumber("5551234567") returns "(555) 123-4567".

Question 4: APPLIED

A teacher stores student grades in a comma-separated string: " alice:92, BOB:85, Charlie:78 ". Write a program that produces the following formatted output: --- GRADE REPORT --- Alice............92 Bob..............85 Charlie..........78 Hint: you will need .trim(), .split(), .padEnd(), and your title case function.
Show answer
First, trim and split the input by ", " to get an array of entries. Then for each entry, split by ":" to separate the name and grade. Title-case the name and use .padEnd() with dots. Here is one approach: const data = " alice:92, BOB:85, Charlie:78 "; const entries = data.trim().split(", "); let report = "--- GRADE REPORT ---\n"; entries.forEach(entry => { let [name, grade] = entry.split(":"); name = name.trim().toLowerCase(); name = name[0].toUpperCase() + name.slice(1); report += name.padEnd(18, ".") + grade + "\n"; }); console.log(report); The program cleans each name, formats it to a consistent width using dot-padding, and appends the grade. The template could also be built with a template literal for the header line.

Question 5: CRITICAL THINKING

A user enters the sentence: "the quick brown fox jumps over the lazy dog". Write a program that produces a word-frequency report. The output should list each unique word alphabetically with its count, formatted like: --- WORD FREQUENCY --- brown........1 dog..........1 fox..........1 ... Discuss which string and array methods you chose and why. What happens if the input has extra spaces or mixed case?
Show answer
First, clean the input with .trim().toLowerCase() to handle mixed case and leading/trailing spaces. Then use .split(" ").filter(w => w.length > 0) to handle extra spaces between words. Build a frequency object by looping through the words array and incrementing a counter for each word. Convert the object's keys to an array with Object.keys(freq).sort() for alphabetical order. Finally, format each line with .padEnd() and assemble the report with a template literal. If the input had extra spaces, .split(" ") would create empty strings, so filtering them out is essential. Using .toLowerCase() ensures that "The" and "the" are counted as the same word. This problem synthesizes cleaning, splitting, data aggregation, sorting, and formatted output — the full text-processing pipeline.

SUMMARY

Lesson Summary

Summary

In this lesson you learned how to build a complete text-processing program in JavaScript that transforms raw input into clear, formatted output. Every program follows the Input → Transform → Output pipeline. You clean data with .trim(), normalize case with .toLowerCase() and .toUpperCase(), extract and rearrange text with .slice(), .split(), and .join(), swap content with .replace() and .replaceAll(), and align columns with .padStart() and .padEnd().

The most important technique for creating readable output is the template literal, which uses backticks and ${} placeholders to embed expressions directly into strings. Because JavaScript strings are immutable, every method returns a new string, enabling method chaining — writing multiple transformations in a single, readable line. Master these tools, and you will be ready to tackle regular expressions and more advanced text-processing challenges in the future.

Varsity Tutors • Computer Programming 1 (JavaScript) • Text Processing Programs