Topic 01

Arrays and Loops

JavaScriptHands-on

Most useful data comes in lists: the projects in a portfolio, the messages in an inbox, the results of a search. One name per item stops working at about the second item, and it cannot cope with a list whose length you do not know in advance. An array is a single value that holds other values in order, and a loop is code that runs once for each of them. Together they are how a page shows ten things, or a thousand, with the code for one.

Picture a queue where everyone holds a numbered ticket, except that the first ticket is number zero. You can call anyone by their number, you can count how long the queue is, and you can walk along it, one person at a time. That is almost everything an array does.

Making and Reading an Array

An array is written in square brackets, with its items separated by commas. Each item has a position called its index, and the first index is 0. One way to remember why: the index is how many steps the item is from the front, and the first item is no steps away. To read an item, write the array's name and then the index in square brackets.

Console
> const tags = ["html", "css", "javascript"];
undefined
> tags[0]
'html'
> tags[2]
'javascript'
> tags.length
3
> tags[tags.length - 1]
'javascript'
> tags[3]
undefined

In the Console above, index 0 gives html, and index 2 gives javascript, the third item. The length property counts the items: 3. Because counting starts at zero, the last item's index is always the length minus one, and the fifth line reads the last item that way, whatever the length. Asking for index 3, past the end, is not an error: the answer is undefined, because nothing is there. The error comes if you then try to use that undefined as if it were something, the type error of Chapter 6.

Changing an Array

Four methods cover most everyday changes and questions. push adds an item to the end and answers with the new length. pop removes the last item and answers with the item it removed. includes asks whether a value is in the array and answers true or false. indexOf answers with the index of the first matching item, or minus one when there is no match.

Console
> tags.push("api");
4
> tags
(4) ['html', 'css', 'javascript', 'api']
> tags.includes("css")
true
> tags.includes("CSS")
false
> tags.indexOf("python")
-1

After the push, the array has four items, and typing its name shows all of them. Chrome puts the number of items in round brackets in front of an array it displays. The first includes answers true. The second answers false, because the comparison is exact and CSS in capitals is a different string from css. And indexOf answers minus one for python, which is not in the list.

Notice that tags was made with const, and yet the array changed. The name still points at the same array; what changed is the inside of the array. That is the promise from Chapter 6: const fixes the name, not the contents. The next topic shows the same thing with objects.

Every Item in Turn: for...of

A for...of loop runs a block of code once for each item of an array, in order. Read it as "for each tag of the tags, run this block". Each time round, the name between the brackets points at the current item.

js/main.js
const tags = ["html", "css", "javascript"];

for (const tag of tags) {
  console.log(`Tag: ${tag}`);
}
Console output
Tag: html
Tag: css
Tag: javascript

The block runs three times, once per item, and the Console shows three lines: Tag: html, Tag: css, Tag: javascript. The name tag can be a const because it is never re-pointed: each pass of the loop makes a fresh tag for the next item. The plural for the array and the singular for each item is a naming habit worth keeping, because it makes loops read like sentences.

A loop can also build something up as it goes. The pattern is called a running total: start with a value before the loop, change it on each pass, and use it after the loop.

js/main.js
const prices = [4.5, 12, 7.25];
let total = 0;

for (const price of prices) {
  total = total + price;
}

console.log(`Total: ${total}`);
Console output
Total: 23.75

The total starts at zero, and it is made with let because it will move. The first pass adds four and a half, the second adds twelve, the third adds seven and a quarter. The console.log sits after the loop's closing brace, so it runs once, at the end, and the Console shows Total: 23.75.

One array: items, indexes and length
Index012
Item"html""css""javascript"
How to read ittags[0]tags[1]tags[2], the last
tags.length3, one more than the last index

Other Loops You Will See

Older code, and code that needs each item's index, uses the counting for loop. Its round brackets hold three parts separated by semicolons: where the counter starts, the condition to keep going, and the step taken after each pass. The two plus signs after the counter's name add one to it.

js/main.js
const tags = ["html", "css", "javascript"];

for (let i = 0; i < tags.length; i++) {
  console.log(i, tags[i]);
}

Read it as: start i at zero, keep going while it is less than the length, and add one after each pass. The Console shows each index and item side by side: 0 html, 1 css, 2 javascript. It does the same job as for...of with more places to make a mistake, which is why this book prefers the shorter loop.

A while loop repeats its block for as long as its condition stays true, for work where you do not know in advance how many passes it will take. If the condition never becomes false, the loop never ends and the browser tab freezes; Chapter 11 comes back to why. You may also meet for...in, which looks similar but walks through the index numbers, as strings, rather than the items. For arrays, use for...of.

Common Confusions
  • "The first item is number 1." It is at index 0, and the last item is at the length minus one. Getting this wrong by one place is so common it has a name: an off-by-one error.
  • "An empty array counts as false." An empty array is truthy, like every array. To ask whether it is empty, check whether its length is zero, with tags.length === 0.
  • "for...in is the loop for arrays." That loop walks the keys, which for an array are the index numbers. Use for...of to get the items themselves.
Why It Matters
  • The project list, the filter buttons and the live data later in this book are all arrays.
  • One loop replaces any amount of copying and pasting, and keeps working when the list grows.

Knowledge Check

An array has 5 items. What is the index of the last one?

  • 5, the same as the number of items
  • 4, one less than the number of items
  • 0, because arrays are counted backwards
  • 6, one more than the number of items

What does ["html", "css"].includes("css") give back?

  • 1, the index where css was found
  • The string css, the item that matched
  • The boolean true, as css is in it
  • A new array with css added to the end

What does this loop log? for (const tag of ["a", "b"]) { console.log(tag); }

  • 0, then 1, the index of each item
  • a, then b, with one item on each line
  • The whole array once, as a single line
  • Only a, since the loop runs a single time

How should a script check whether an array called tags is empty?

  • Check whether tags.length === 0
  • Check whether tags is truthy at all
  • Check whether tags === undefined
  • Check whether tags.includes(0)

You got correct