Skip to main content
Back to module
JavaScript Essentials · Language Fundamentals

Quote of the Day

Reading24mLesson 3 of 4 in this module

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], not list[list.length].
  • Math.round instead of Math.floor. It can produce an index equal to length.
  • 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, not 3, so adding a quote does not break anything.

Quick recap

  • Arrays are zero-indexed lists; length - 1 is 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.

Also in this lesson: