Combine an array and a few small functions into a mini program that picks and formats a quote.
Why this matters
Knowing what variables and functions are is one thing. Putting them together into a working program is another, and it is the skill employers actually test. This lesson is a small project: a "quote of the day" picker. It is tiny, but it has the same shape as real features: some data, a few functions that each do one job, and output that combines them.
The data: an array of quotes
An array is an ordered list of values, written with square brackets:
const quotes = [
"Simplicity is prerequisite for reliability. (Edsger Dijkstra)",
"Make it work, make it right, make it fast. (Kent Beck)",
"Programs must be written for people to read. (Harold Abelson)"
];
quotes.length; // 3
quotes[0]; // the first quote (arrays count from 0)
quotes[2]; // the last quote
quotes[3]; // undefined: there is no fourth item
Two facts cause most array bugs. Indexes start at 0, and the last index is length - 1. You will see both in the next step.
Step 1: a random index
Math.random() returns a decimal from 0 (included) up to 1 (never quite reached), such as 0.4172. To turn that into an index:
const r = Math.random(); // e.g. 0.83
const index = Math.floor(r * quotes.length); // 0.83 * 3 = 2.49 -> 2
Math.floor rounds down. Because r is always below 1, r * 3 is always below 3, so the index is always 0, 1 or 2: exactly the valid positions. Using Math.round instead would sometimes produce 3, which is out of range, and the first and last items would come up less often.
Step 2: make it testable
Random code is hard to test because the answer changes every run. A good trick is to pass the random number in as a parameter. Then the function is predictable when you give it a known number and random when you give it Math.random():
function pickQuote(list, randomNumber) {
if (list.length === 0) return null; // edge case: nothing to pick
return list[Math.floor(randomNumber * list.length)];
}
pickQuote(quotes, 0); // always the first quote
pickQuote(quotes, 0.99); // always the last quote
pickQuote(quotes, Math.random()); // a random one
Notice the edge case: an empty list. Without the guard, list[0] would be undefined, and the code that formats the quote later might crash. Returning null on purpose makes "no quote" an explicit answer.
Step 3: the same quote all day
A "quote of the day" should not change every time you refresh. Instead of a random number, use a number that is the same all day, such as the day of the year, and the remainder operator %:
function quoteOfTheDay(list, dayNumber) {
return list[dayNumber % list.length];
}
quoteOfTheDay(quotes, 0); // quotes[0]
quoteOfTheDay(quotes, 4); // 4 % 3 = 1 -> quotes[1]
quoteOfTheDay(quotes, 5); // 5 % 3 = 2 -> quotes[2]
% gives what is left over after division, so it wraps around: day 3 is back to the first quote. This "wrap around with %" pattern appears everywhere: carousels, rotating shifts, game turns.
To get a day number from the real date you could use Math.floor(Date.now() / 86400000), the number of whole days since 1 January 1970 (86,400,000 is the number of milliseconds in a day).
Step 4: format the output
Keep formatting separate from choosing. That way you can change how a quote looks without touching the selection logic:
function formatQuote(quote) {
return `Today: "${quote}"`;
}
const today = Math.floor(Date.now() / 86400000);
console.log(formatQuote(quoteOfTheDay(quotes, today)));
Each function is small enough to check in your head, and the last line reads almost like a sentence. That is the goal.
Common mistakes
- Off-by-one indexes. The last item is
list[list.length - 1], notlist[list.length]. Math.roundinstead ofMath.floor. It can produce an index equal tolength.- Forgetting the empty list. Decide what should happen and handle it first.
- Mixing jobs in one function. Picking, formatting and printing are three jobs; keep them apart so each is easy to test.
- Hard-coding the length. Write
list.length, not3, so adding a quote does not break anything.
Quick recap
- Arrays are zero-indexed lists;
length - 1is the last index. Math.floor(Math.random() * list.length)gives a valid random index.- Passing the random number in makes a function testable.
%wraps a growing number around a list.- Small functions, one job each, combined at the end.
Try it
Open the Do tab and build the quote program: add your own quotes, then write pickQuote, quoteOfTheDay and formatQuote.