Arrays: many values under one name
A variable holds one thing. An array holds many, in order, under a single name — and almost every useful program has one in it somewhere.
Making an array
Square brackets, values separated by commas:
const scores = [10, 8, 9, 7];
const names = ["Ayesha", "Bilal", "Chen"];
console.log(scores);
console.log(names);
console.log(names.length);
[ 10, 8, 9, 7 ] [ 'Ayesha', 'Bilal', 'Chen' ] 3
length is not a function — there are no brackets after it. It is a property
the array keeps up to date for you.
Getting one item out
Square brackets again, this time with a position:
const names = ["Ayesha", "Bilal", "Chen"];
console.log(names[0]);
console.log(names[1]);
console.log(names[2]);
Ayesha Bilal Chen
Positions start at zero. The first item is names[0], not names[1].
This feels wrong to everyone at first. A way of thinking about it that sticks: the number is not "which item" but "how far along from the start". The first item is zero steps from the start.
So the last item of a three-item array is at position 2. Ask for position 3 and JavaScript does something quietly dangerous:
const names = ["Ayesha", "Bilal", "Chen"];
console.log(names[3]);
undefined
No error. No warning. Just undefined, which then travels through your program
until it breaks something far away from the line that caused it. Python stops
dead with list index out of range; JavaScript hands you a shrug. Getting used
to that difference saves hours later.
Counting to the end yourself is easy to get wrong, so there are two better ways:
const names = ["Ayesha", "Bilal", "Chen"];
console.log(names[names.length - 1]);
console.log(names.at(-1));
Chen Chen
at(-1) means "the last one", at(-2) the one before it. It stays correct when
the array changes size, which counting never does.
const does not mean frozen
This surprises people who have just learned const:
const scores = [10, 8, 9];
scores.push(7);
scores[0] = 100;
console.log(scores);
[ 100, 8, 9, 7 ]
const was not broken. It promises that the name scores will always point
at this same array — it says nothing about what is inside it. Try
scores = [1, 2] and you get a TypeError; changing the contents is fine.
Nearly all arrays are declared const for exactly this reason. You almost never
want to repoint the name, and you almost always want to change the contents.
Adding and removing
Four methods, and their names say which end they work on:
const queue = ["Ayesha", "Bilal"];
queue.push("Chen"); // add to the end
queue.unshift("Dania"); // add to the front
console.log(queue);
const first = queue.shift(); // take from the front
const last = queue.pop(); // take from the end
console.log(first, last);
console.log(queue);
[ 'Dania', 'Ayesha', 'Bilal', 'Chen' ] Dania Chen [ 'Ayesha', 'Bilal' ]
push and pop work on the end, unshift and shift on the front. All four
change the array itself rather than handing back a new one:
const scores = [1, 2];
const result = scores.push(3);
console.log(scores);
console.log(result);
[ 1, 2, 3 ] 3
scores changed, and push returned 3 — the new length, not the array. So
const bigger = scores.push(4) does not give you a bigger array. It gives you a
number, and quietly modifies the array you already had.
Searching, and the trap this lesson is really about
indexOf tells you where something is:
const names = ["Ayesha", "Bilal", "Chen"];
console.log(names.indexOf("Bilal"));
console.log(names.indexOf("Dania"));
1 -1
-1 means "not in here". There is no position -1, so it is a safe answer to
give — and it is the single most misused value in the language.
Here is the code almost everyone writes next:
const names = ["Ayesha", "Bilal", "Chen"];
if (names.indexOf("Ayesha")) {
console.log("Ayesha is here");
} else {
console.log("Ayesha is not here");
}
Ayesha is not here
Ayesha is here. She is first, at position 0 — and 0 is falsy, so the if
takes the wrong branch. The one person the check is most likely to be asked
about is the one person it always gets wrong.
Now the other half, which is worse because it looks like it works:
const names = ["Ayesha", "Bilal", "Chen"];
if (names.indexOf("Dania")) {
console.log("Dania is here");
}
Dania is here
Dania is nowhere near this array. indexOf returned -1, and -1 is a
perfectly ordinary non-zero number, so it is truthy. The check reports the
opposite of the truth in both directions.
The fix is to compare against -1 rather than leaning on truthiness:
const names = ["Ayesha", "Bilal", "Chen"];
console.log(names.indexOf("Ayesha") !== -1);
console.log(names.indexOf("Dania") !== -1);
true false
Better still, when you only want a yes or no, say so:
const names = ["Ayesha", "Bilal", "Chen"];
console.log(names.includes("Ayesha"));
console.log(names.includes("Dania"));
true false
includes gives back true or false, so there is nothing to misread. Reach
for indexOf only when you actually need the position.
Walking through every item
This is where arrays earn their keep:
const names = ["Ayesha", "Bilal", "Chen"];
for (const name of names) {
console.log(`Hello, ${name}!`);
}
Hello, Ayesha! Hello, Bilal! Hello, Chen!
No counting, no positions, no chance of an off-by-one. for...of hands you one
item at a time, and it is what you want almost every time.
Note for...of, not for...in. for...in walks the keys, which for an array
means the strings "0", "1", "2" — rarely what anyone wants and a common
source of confusing bugs.
The building-up pattern, now on real data:
const scores = [10, 8, 9, 7, 6];
let total = 0;
for (const score of scores) {
total += score;
}
console.log(`Total: ${total}`);
console.log(`Average: ${total / scores.length}`);
Total: 40 Average: 8
total is let, not const, because that name really does get repointed on
every pass. Writing this loop once is worth doing, so you know what the shorter
methods in the next lesson are actually doing on your behalf.
Your turn
The array towns is already set up. Print the FIRST town, then the LAST town, each on its own line. Do not count the items by hand — the checker adds a town before running your code.
A queue of names is given. Add "Chen" to the END and "Dania" to the FRONT, then print the whole queue on one line.
The array present holds who turned up today. Print "Ayesha is here" if she is in the array and "Ayesha is absent" if she is not. Careful: she is first in the list, and the obvious version of this check gets that case wrong.
Print the middle item of the array marks. It always has an odd number of items, so there is exactly one middle. Work it out from the length — the checker runs your code against a longer array too.
Prefer learning with a teacher?
WasiLearn Academy runs small-group classes covering this material, online and in Karachi.
See the classes