Skip to main content

Chapter 8 - Strings and Text Editing (JavaScript)

Here's a JavaScript-flavoured version of the same concepts, with small JS examples for each idea.


String literals and escape sequences​

You can write strings with single quotes, double quotes, or backticks. Backslash escape sequences like \', \", \n, \t, and \\ work the same way.

Example:

const spam = "That is Alice's cat.";
const spam2 = 'Say hi to Bob\'s mother.';
console.log("Hello there!\nHow are you?\nI'm doing fine.");

Raw strings with String.raw​

JavaScript has no r prefix, but String.raw with a tagged template literal treats backslashes as literal characters.

Example:

console.log(String.raw`The file is in C:\Users\Alice\Desktop`);
console.log(String.raw`Hello...\n\n...world!`); // backslashes shown literally

Multiline strings (template literals)​

Backtick strings (template literals) naturally span multiple lines, combining Python's triple-quote and f-string features.

Example:

console.log(`Dear Alice,

Can you feed Eve's cat this weekend?

Sincerely,
Bob`);

// JavaScript uses // or /* */ for comments, not multiline strings
/* This is a test program.
Written by Alice.
This serves as a multiline comment. */

String indexing and slicing​

Access characters by index (starting at 0). Use .at() for negative indexes and .slice() for substrings.

Example:

const greeting = "Hello, world!";
console.log(greeting[0]); // 'H'
console.log(greeting.at(-1)); // '!'
console.log(greeting.slice(0, 5)); // 'Hello'
console.log(greeting.slice(7, -1)); // 'world'
console.log(greeting.slice(7)); // 'world!'

includes() (equivalent of in)​

You can test if a substring appears inside another string using .includes().

Example:

console.log("Hello, world".includes("Hello"));      // true
console.log("Hello, world".includes("HELLO")); // false
console.log(!"cats and dogs".includes("cats")); // false

Template literals (like f-strings)​

Backtick strings with ${} embed expressions directly, instead of manual concatenation.

Example:

const name = "Al";
const age = 4000;
console.log(`My name is ${name}. I am ${age} years old.`);
console.log(`In ten years I will be ${age + 10}`);

Literal braces (no special escaping needed — only ${} is interpolated):

console.log(`{name}`);  // prints {name}

Older formatting: concatenation​

Before template literals, string concatenation was the main approach.

Example:

const name = "Al";
const age = 4000;
console.log("My name is " + name + ". I am " + age + " years old.");

Changing case: toUpperCase(), toLowerCase()​

toUpperCase() / toLowerCase() return new strings. JavaScript has no built-in isupper() / islower(), but you can compare against the converted version.

Example:

const spam = "Hello, world!";
console.log(spam.toUpperCase()); // 'HELLO, WORLD!'
console.log(spam.toLowerCase()); // 'hello, world!'
console.log("HELLO" === "HELLO".toUpperCase()); // true (all upper)
console.log("abc123" === "abc123".toLowerCase()); // true (all lower)

Case-insensitive check:

const feeling = prompt("How are you?");
if (feeling.toLowerCase() === "great") {
console.log("I feel great too.");
} else {
console.log("I hope the rest of your day is good.");
}

Character type checks with regex​

JavaScript has no built-in isalpha(), isalnum(), isdecimal(), isspace(), or istitle(), but regex handles all of these.

Example:

console.log(/^[a-zA-Z]+$/.test("hello"));          // true (only letters)
console.log(/^[a-zA-Z0-9]+$/.test("hello123")); // true (letters and numbers)
console.log(/^\d+$/.test("123")); // true (only digits)
console.log(/^\s+$/.test(" ")); // true (only whitespace)

Simple input validation:

let age;
while (true) {
age = prompt("Enter your age:");
if (/^\d+$/.test(age)) break;
console.log("Please enter a number for your age.");
}

let password;
while (true) {
password = prompt("Select a new password (letters and numbers only):");
if (/^[a-zA-Z0-9]+$/.test(password)) break;
console.log("Passwords can only have letters and numbers.");
}

startsWith() and endsWith()​

Check if a string begins or ends with a given substring.

Example:

const s = "Hello, world!";
console.log(s.startsWith("Hello")); // true
console.log(s.endsWith("world!")); // true
console.log("abc123".startsWith("abc")); // true

Joining and splitting strings​

  • array.join('sep') builds one string from many.
  • 'text'.split() does not split on whitespace by default in JS — use .split(/\s+/) or .split(' ').

Examples:

console.log(["cats", "rats", "bats"].join(", "));  // 'cats, rats, bats'
console.log(["My", "name", "is", "Simon"].join(" ")); // 'My name is Simon'

console.log("My name is Simon".split(" ")); // ['My', 'name', 'is', 'Simon']
console.log("MyABCnameABCisABCSimon".split("ABC")); // ['My', 'name', 'is', 'Simon']

Split multiline string into lines:

const spam = `Dear Alice,
There is a milk bottle in the fridge
that is labeled "Milk Experiment."

Please do not drink it.
Sincerely,
Bob`;
const lines = spam.split("\n");

Text alignment: padStart(), padEnd()​

These methods pad strings to a given total width, optionally with a fill character. JavaScript has no built-in center().

Example:

console.log("Hello".padStart(10));          // '     Hello'
console.log("Hello".padEnd(10, "-")); // 'Hello-----'

// center helper
function center(str, width, fill = " ") {
const pad = Math.max(0, width - str.length);
const left = Math.floor(pad / 2);
return fill.repeat(left) + str + fill.repeat(pad - left);
}
console.log(center("Hello", 20, "=")); // '=======Hello========'

Trimming whitespace or specific characters: trim(), trimStart(), trimEnd()​

Remove whitespace from the ends of a string. JavaScript's trim doesn't accept a character set, but you can use regex for that.

Example:

const spam = "   Hello, World   ";
console.log(spam.trim()); // 'Hello, World'
console.log(spam.trimStart()); // 'Hello, World '
console.log(spam.trimEnd()); // ' Hello, World'

Strip specific characters (with regex):

const spam2 = "SpamSpamBaconSpamEggsSpamSpam";
console.log(spam2.replace(/^[ampS]+|[ampS]+$/g, "")); // 'BaconSpamEggs'

Unicode code points: charCodeAt() and String.fromCharCode()​

charCodeAt() gives the integer code point for a character; String.fromCharCode() does the reverse.

Example:

console.log("A".charCodeAt(0));   // 65
console.log("!".charCodeAt(0)); // 33
console.log(String.fromCharCode(65)); // 'A'
console.log(String.fromCharCode("A".charCodeAt(0) + 1)); // 'B'

Clipboard access​

In the browser, use the async Clipboard API. In Node.js, use a package like clipboardy.

Example (browser):

await navigator.clipboard.writeText("Hello, world!");
const text = await navigator.clipboard.readText();
console.log(text); // 'Hello, world!'

Alternating-case program (browser):

let text = await navigator.clipboard.readText();
let altText = "";
let makeUpper = false;

for (const ch of text) {
altText += makeUpper ? ch.toUpperCase() : ch.toLowerCase();
makeUpper = !makeUpper;
}

await navigator.clipboard.writeText(altText);
console.log(altText);

Project: bulletPointAdder (add bullets to lines)​

Reads text from clipboard, adds * to each line, writes back to clipboard using .split('\n') and .join('\n').

Core version (browser):

let text = await navigator.clipboard.readText();
const lines = text.split("\n");
for (let i = 0; i < lines.length; i++) {
lines[i] = "* " + lines[i];
}
text = lines.join("\n");
await navigator.clipboard.writeText(text);

Project: Pig Latin translator​

Transforms each word into Pig Latin while preserving punctuation and capitalization using string methods like split, regex character checks, toLowerCase, toUpperCase, and join.

Very compact sketch:

const message = prompt("Enter the English message to translate into pig latin:");
const VOWELS = ["a", "e", "i", "o", "u", "y"];
const pigLatin = [];

for (let word of message.split(" ")) {
let prefixNon = "";
while (word.length > 0 && !/[a-zA-Z]/.test(word[0])) {
prefixNon += word[0];
word = word.slice(1);
}
if (word.length === 0) {
pigLatin.push(prefixNon);
continue;
}

let suffixNon = "";
while (!/[a-zA-Z]/.test(word.at(-1))) {
suffixNon = word.at(-1) + suffixNon;
word = word.slice(0, -1);
}

const wasUpper = word === word.toUpperCase();
const wasTitle = word[0] === word[0].toUpperCase() && word.slice(1) === word.slice(1).toLowerCase();
word = word.toLowerCase();

let prefixCons = "";
while (word.length > 0 && !VOWELS.includes(word[0])) {
prefixCons += word[0];
word = word.slice(1);
}

if (prefixCons) {
word = word + prefixCons + "ay";
} else {
word = word + "yay";
}

if (wasUpper) {
word = word.toUpperCase();
} else if (wasTitle) {
word = word[0].toUpperCase() + word.slice(1);
}

pigLatin.push(prefixNon + word + suffixNon);
}

console.log(pigLatin.join(" "));

Overall idea of the chapter​

The chapter's main message is: JavaScript has a strong set of string methods that mirror Python's capabilities. Template literals combine f-string interpolation with multiline strings in one syntax. The core operations (searching, splitting, trimming, case conversion) are nearly identical between the two languages, and even complex programs like a Pig Latin translator translate directly.