From one value to many
Lesson 3-3 introduced the loop that visits each item of a collection with no counter at all: for (const item of collection). That is JavaScript's version of Python's for item in collection, and so far it has only been used on a string.
This unit gives it something much more useful to walk. Every variable up to now has held a single value, one number or one string, but real data arrives in bunches, and holding a bunch is what arrays are for.
Arrays are JavaScript's lists
Real data comes in bunches: search results, chat messages, rows of a spreadsheet. An array lets one variable hold the whole bunch in order, which is what gives the loops from unit 3 something worth looping over.
What Python calls a list, JavaScript calls an array. Same square brackets, same zero-based indexing:
const fruits = ["apple", "banana", "cherry"]; console.log(fruits[0]); // "apple" console.log(fruits.length); // 3
Two differences from Python to absorb:
- Length is the
.lengthproperty (no parentheses), notlen(...). - Negative indexes do not work.
fruits[-1]isundefined, not the last item. Usefruits[fruits.length - 1]or the modern methodfruits.at(-1).
And one JavaScript quirk: reading an index that does not exist gives undefined instead of raising an error like Python's IndexError. Your program keeps running, often with confusing results later, so watch your bounds.
Four ways to reach into an array
The most common array reads in one program: the first item, the size, and two different routes to the last item. The final line shows what a negative index actually does.
const fruits = ["apple", "banana", "cherry"]; console.log(fruits[0]); console.log(fruits.length); console.log(fruits[fruits.length - 1]); console.log(fruits.at(-1)); console.log(fruits[-1]);
Output
apple 3 cherry cherry undefined
The two routes to "cherry" are worth comparing. fruits[fruits.length - 1] computes the last index by hand, which works everywhere and appears in code of every vintage. fruits.at(-1) is the modern method that counts from the end for you, and it reads far better. The last line is the trap: fruits[-1] does not error, it simply reports undefined, because square brackets take a position and there is no position -1.
Reading the ends and the size of an array
Three of the four reads above, applied to a fresh array of color names.
const colors = ["red", "green", "blue"]; console.log(colors[0]); console.log(colors.at(-1)); console.log(colors.length);
Output
red
blue
3colors is declared const even though arrays are for changing, and that is not a contradiction. const prevents the name from being pointed at a different array. It says nothing about the items inside, which can still be added, removed, and replaced. Lesson 5-4 explains why in full, and until then it is safe to keep declaring arrays with const as this course does.
Reading past the end of an array
Given const nums = [10, 20, 30];, the expression nums[3] gives undefined, because that slot does not exist. The valid indexes for a three-item array are 0, 1, and 2, since counting starts at zero and stops one short of the length.
Unlike Python, which raises IndexError the instant you read out of range, JavaScript quietly hands back undefined and lets the program continue. That difference is the reason off-by-one bugs can hide for a long time in JavaScript. The crash, when it eventually comes, happens somewhere else entirely, usually as a message about reading a property of undefined several lines later.
Expression on [10, 20, 30] | Result |
|---|---|
nums[0] | 10 |
nums[2] | 30, the last valid index |
nums[3] | undefined, one past the end |
nums[-1] | undefined, no such position |
nums.at(-1) | 30, counts from the end |