3.3 Arrays
SLO 2
Describe the principles of structured programming.
Structured programming needs data it can count through: thirty separately named variables defeat a loop, one array does not. Naming a whole collection once, and reaching any element by its index, is what lets iteration act on data of any size.
SLO 3
Describe, design, implement, and test structured programs using currently accepted methodology.
The build-and-return shape you implement here — start an empty array, loop, push what qualifies, return it — is a design small enough to test on its own, including the case where nothing qualifies and the honest answer is an empty array.
Learning Objectives
By the end of this section you should be able to:
- Explain why a list is a better tool than many separately named variables.
- Create an array and read any element from it using an index.
- Explain why the first element is at index
0, and whatlengthcounts. - Change, add, and remove elements at either end of an array.
- Walk through every element with a
forloop and with afor...ofloop. - Pass an array into a function and build a new array to return.
3.3.1 When One Name Is Not Enough
Every variable so far has held exactly one value. That works until you need to keep several of the same kind of thing — three test scores, say.
▶ Press Run to see the output…
What you should see:
First score: 88 Total: 259
That is fine for three. Now imagine a class of thirty. You would need thirty variables, thirty names to invent, and a thirty-term addition written by hand. Worse, you could not write a loop over them: score1 and score2 are unrelated names as far as JavaScript is concerned, and a loop has no way to say "the next one".
What you actually want is one name for the whole collection, and a way to ask for the first, the second, or the twenty-ninth.
3.3.2 Making a List and Reading From It
Write the values inside square brackets, separated by commas:
The problem here is not typing. It is that separate variables cannot be counted through. Everything you learned about loops in Chapter 2 is useless against thirty named variables, and becomes powerful the moment those values live in one list.
▶ Press Run to see the output…
What you should see:
[88,92,79] 88 79
One name, three values. The number in square brackets after the name picks which one you want.
An array is an ordered collection of values stored under a single name. The values are called elements, and their order is part of the data — the first element stays first until you change it.
Definition 3.3.1 - An array is an ordered collection of values stored under a single name. The values are called elements, and their order is part of the data - the first element stays first until you change it.
An index is the position number of an element in an array, counting from 0. Writing scores[2] means "the element of scores at index 2", which is the third element.
Definition 3.3.2 - An index is the position number of an element in an array, counting from 0. Writing scores[2] means the element of scores at index 2, which is the third element.
Counting from zero is the part everyone trips on. Read the index as how far from the start, not as a place in a queue: the first element is zero steps from the start, so it is scores[0].
▶ Press Run to see the output…
What you should see:
green undefined
Index 3 is past the end — there is no fourth element. JavaScript does not stop the program or report an error; it hands back undefined, the same "no value here" you met in Section 1.2 and again in Section 3.2 when a function had no return.
How many are there?
▶ Press Run to see the output…
What you should see:
3 blue
lengthThe length property of an array is the number of elements it holds. Because indexes start at 0, the last element is always at index length - 1.
Definition 3.3.3 - The length property of an array is the number of elements it holds. Because indexes start at 0, the last element is always at index length - 1.
That - 1 is worth saying out loud: three elements, indexes 0, 1, 2. The length is one more than the last index, every time.
JavaScript also offers a shortcut for counting from the end:
▶ Press Run to see the output…
What you should see:
blue green
at(-1) is the last element, at(-2) the one before it. Square brackets do not do this — colors[-1] is undefined, because -1 is simply an index that does not exist.
1. Given let days = ["Mon", "Tue", "Wed"];, what does days[1] return?
"Mon""Tue""Wed"
Solution
b. "Tue". Index 1 is one step from the start, so it is the second element.
2. For that same array, what is days.length, and what is the index of the last element?
- Length 3, last index 3
- Length 3, last index 2
- Length 2, last index 2
Solution
b. Length 3, last index 2. The length counts the elements; the last index is length - 1 because counting starts at 0.
3. What does days[5] produce?
- An error that stops the program
undefined"Wed", the closest element
Solution
b. undefined. Reading past the end is not an error in JavaScript — which is exactly why it is easy to miss.
Make an array called planets holding "Mercury", "Venus", and "Earth". Print the first planet, the last planet using length - 1, and how many planets there are.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
Mercury Earth 3
planets.at(-1) would also give you the last one.
Every array so far has been typed out by hand. Most real data does not arrive that way — it arrives as text, with something separating the pieces.
.split() cuts a string into an array wherever it finds the separator you name:
▶ Press Run to see the output…
An array of three strings, and every array operation in this section now applies to it. Split on a space instead and you get words:
▶ Press Run to see the output…
.join() goes the other way, gluing an array back into one string with whatever you put between the pieces:
▶ Press Run to see the output…
Neither one changes what it was called on. .split() leaves the string alone and hands back a new array; .join() leaves the array alone and hands back a new string. That is the same promise Section 1.2.3 made about string methods, and it holds here.
3.3.3 Changing What Is in a List
An element is assigned to just like a variable — put the indexed name on the left of the =:
These two are worth remembering as a pair, because together
they are the usual way to work on text: split it into pieces, do array work on
the pieces, and join the result back. A great many text problems that sound
hard turn out to be an array problem with a .split() at the front and a
.join() at the end.
An out-of-range index is one of the quietest bugs in this chapter. Nothing turns red. You get undefined, and it travels — add it to a number and you get NaN several lines later, in code that looks innocent. When a calculation on array data comes out NaN, suspect an index before you suspect the arithmetic.
▶ Press Run to see the output…
What you should see:
["red","yellow","blue"]
The array did not grow; the middle slot now holds something else.
An array can hold values of different types at once, though in practice a list is usually one kind of thing:
▶ Press Run to see the output…
What you should see:
[42,"hello",true] 3
3.3.4 Adding and Removing at the Ends
An array's size is not fixed. Four methods change it, one for each combination of which end and add or remove:
Notice what the printed array looks like: strings come out wrapped in quotes, numbers and booleans bare. That is the console showing you the type of each element, not decoration. ["42"] and [42] print differently on purpose, and telling them apart will save you an afternoon later.
| Method | What it does |
|---|---|
push(value) |
adds to the end |
pop() |
removes from the end, and returns it |
unshift(value) |
adds to the start |
shift() |
removes from the start, and returns it |
▶ Press Run to see the output…
What you should see:
["Marisol","Dev","Priya"] ["Sam","Marisol","Dev","Priya"]
The two removers hand back what they removed, so you can use it:
▶ Press Run to see the output…
What you should see:
3 [1,2] 2
pop() did two things at once — it shortened the array and returned the removed value. That is the same double job return does in Section 3.2, and it is why let last = stack.pop(); reads naturally.
A waiting line is an array where people join at the back and get served from the front. Build one, add a latecomer, then serve whoever is first.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
Now serving: Marisol ["Dev","Priya"] Still waiting: 2
shift() returned "Marisol" and removed her in one step, and everyone else moved up an index — Dev is now at index 0.
1. After let a = [1, 2]; a.push(3);, what is a?
[3,1,2][1,2,3][1,3]
Solution
b. [1,2,3]. push always adds at the end.
2. What does pop() return?
- The shortened array
- The element it removed
- Nothing — it only changes the array
Solution
b. The element it removed. The array is shortened as a side effect, and the removed value comes back to you.
3. You want to remove the first element of queue and keep it. Which line does that?
let first = queue.pop();let first = queue.shift();let first = queue[0];
Solution
b. let first = queue.shift();. Option a takes from the wrong end. Option c reads the first element but leaves it in the array.
Start with an array tasks holding "wash" and "dry". Add "fold" to the end, add "sort" to the front, then remove the last task and print both the removed task and the array that remains.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
Removed: fold ["sort","wash","dry"]
3.3.5 Walking Through a List
This is what arrays were for. A for loop from Chapter 2 can count indexes from 0 up to length - 1:
▶ Press Run to see the output…
What you should see:
Score 0: 88 Score 1: 92 Score 2: 79
Read the loop header carefully, because its shape is not an accident. It starts at 0 because that is the first index, and it continues while i < scores.length — less than, not less than or equal. With three elements the last valid index is 2, so stopping before 3 is exactly right. Writing i <= scores.length runs one extra round and reads scores[3], which is undefined.
A loop that does not count
Often you do not care about the index — you just want each value in turn. for...of does that:
That one-too-many mistake is common enough to have a name — an off-by-one error. The cure is not to memorize < versus <=; it is to say the condition aloud as a sentence: "keep going while i is a real index". Index 3 is not a real index of a three-element array.
▶ Press Run to see the output…
What you should see:
88 92 79
for...of LoopA for...of loop runs its body once for each element of an array, assigning that element to a variable you name. It has no counter and no condition, so it cannot run off the end.
Definition 3.3.4 - A for...of loop runs its body once for each element of an array, assigning that element to a variable you name. It has no counter and no condition, so it cannot run off the end.
Both loops visit every element. Choose by what the body needs:
| Use | When |
|---|---|
for...of |
you need the values only — shorter, and no off-by-one is possible |
for with i |
you need the position too, or you want to change elements in place |
You need the counting form to modify elements, because for...of hands you a copy of each value rather than a way back into the slot it came from.
Add up a list of prices and report the average.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
Total: 15 Average: 5
Starting total at 0 matters — leaving it undefined makes every addition NaN. This running-total shape appears constantly: set an accumulator before the loop, change it inside, use it after.
1. Why does for (let i = 0; i < arr.length; i++) use < rather than <=?
<=is not valid in aforloop- The last index is
length - 1, so stopping beforelengthis correct - It makes the loop run faster
Solution
b. The last index is length - 1. Using <= reads one past the end and gets undefined.
2. Which loop would you use to print each name in names, with no position needed?
for (let name of names)for (let i = 0; i <= names.length; i++)- Neither — you cannot loop over an array
Solution
a. for (let name of names). It gives you the values directly and cannot run off the end.
3. What is printed by this code?
▶ Press Run to see the output…
624[2,4]
Solution
a. 6. total starts at 0, becomes 2, then 6. It is a number the whole way, so + adds rather than joins text.
Given an array of temperatures [18, 24, 31, 15], loop over it and print only the temperatures above 20. Then print how many there were.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
24 31 Warm days: 2
3.3.6 Arrays and Functions
An array goes into a function like any other value — one parameter holds the whole list:
▶ Press Run to see the output…
What you should see:
45 7
Starting best at numbers[0] rather than at 0 is deliberate: a list of temperatures below freezing would never beat 0, and the function would wrongly answer 0. Beginning with a real element from the list means the answer is always one of the values you were given.
A function can also hand an array back, and the usual way to build one is to start empty and push:
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
[72,90] []
The second call returns [], an empty array — not undefined and not an error. A function that builds a list should return an empty one when nothing qualifies, so the caller can loop over the result without checking first.
The shape in Example 3.3.3 — make an empty array, loop, push what you want, return it — is the single most reusable pattern in this chapter. Section 3.7 will show you .map(), which writes this same idea in one line. Learning the loop first is the point: .map() is a shortcut for something you can already do by hand, and shortcuts you cannot unpack are hard to debug.
One thing to watch for, which Section 3.6 takes up properly. A number handed to a function is copied, so the function cannot change the caller's copy. An array is not copied — the function receives a way back to your array, so a push inside a function is visible outside it. Example 3.3.3 sidesteps this by building a brand-new result and leaving the input untouched.
Write a function doubled(numbers) that returns a new array with every number multiplied by two, leaving the original array unchanged. Prove it by printing both arrays after the call.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
[2,4,6] [1,2,3]
original is untouched because nothing was pushed into it — every new value went into result.
3.3.7 Lists Inside Lists
An element can itself be an array, which is how you store a grid, a board, or a table of rows:
▶ Press Run to see the output…
What you should see:
[1,2] 5 3
Read grid[2][0] left to right: grid[2] is the third inner array, [5, 6], and [0] takes its first element, 5.
grid.length is 3 — the number of rows, not the number of numbers. The outer array knows nothing about how long its rows are.
A nested loop from Section 2.4 visits every cell:
▶ Press Run to see the output…
What you should see:
1 2 3 4
The outer loop walks the rows; the inner loop walks the cells of whichever row it was handed.
Build a 2-by-2 grid of the numbers 10, 20, 30, 40. Print the value in the second row, second column, then use a nested loop to add every number in the grid and print the total.
▶ Press Run to see the output…
Solution
▶ Press Run to see the output…
Output:
40 Total: 100
Problem Set 3.3
3.3.1 What index does the first element of a JavaScript array have, and why is the last one at length - 1?
Solution
Step 1 — Name the first index:
The first element of a JavaScript array is at index 0. Read the index as how far from the start rather than as a place in a queue: the first element is zero steps from the start, so it is arr[0].
Step 2 — Count what length counts:
length counts elements, not indexes. An array of three elements has length 3, and its indexes are 0, 1, 2.
Step 3 — Put the two together:
Because counting starts one place earlier than 1, every index is one less than the count that reaches it. The last of three elements is the third one, so its index is 3 - 1, which is 2.
Answer: The first element is at index 0. The last element is at length - 1 because length counts the elements while indexes count steps from the start — with n elements the indexes run 0 through n - 1, so the final index is always one less than the length.
3.3.2 Create an array called colors containing "red", "green", and "blue", then write the one line that replaces "green" with "yellow".
▶ Press Run to see the output…
Solution
Step 1 — Build the array: Write the three strings inside square brackets, separated by commas, and give the whole thing one name.
Step 2 — Find the slot to change:
"green" is the second element, and the second element is one step from the start, so it is at index 1.
Step 3 — Assign to that slot:
An element is assigned to just like a variable — put the indexed name on the left of the =. That is the one line the question asks for: colors[1] = "yellow";
▶ Press Run to see the output…
Output:
["red","yellow","blue"]
Answer: let colors = ["red", "green", "blue"]; creates the array, and colors[1] = "yellow"; is the single line that replaces "green". The array does not grow — the middle slot simply holds something else.
3.3.3 What does this print, and why is the second line not an error?
▶ Press Run to see the output…
Solution
Step 1 — Read the first console.log:
days holds three strings, so its indexes are 0, 1, and 2. days[2] is two steps from the start, which is the third and last element, "Wed".
Step 2 — Read the second console.log:
days[7] asks for an element seven steps from the start. There is no such element — the array stops at index 2.
Step 3 — Say what JavaScript does about it:
Reading past the end of an array is not an error in JavaScript. It does not stop the program and it does not report anything; it simply hands back undefined, the same "no value here" that a function without a return produces.
Answer: It prints Wed and then undefined. The second line is not an error because JavaScript treats an out-of-range index as a slot that merely has no value in it, not as an illegal request — which is exactly why this bug is so quiet. The undefined travels: add it to a number and you get NaN several lines later, in code that looks innocent.
3.3.4 Explain the difference between days.pop() and days.at(-1). Which one changes the array?
Solution
Step 1 — Say what each one gives you:
Both hand back the last element. days.pop() removes the last element and returns it. days.at(-1) reads the last element and returns it.
Step 2 — Ask what happens to the array:
pop() shortens the array by one — that is its whole job, and returning the removed value is the bonus that lets you write let last = days.pop();. at(-1) touches nothing; the array is exactly as long after the call as before it.
Step 3 — Match each to a purpose:
Use pop() when you want the element out of the array. Use at(-1) when you only want to look at it and leave the array alone.
Answer: days.pop() changes the array — it removes the last element and returns it. days.at(-1) only reads the last element and leaves the array untouched. They return the same value on the first call, but repeat them and they diverge immediately: a second pop() returns the new last element, while a second at(-1) returns the same one again.
3.3.5 Given let nums = [10, 20, 30, 40, 50];, what do nums.at(-2) and nums[nums.length - 2] each return?
Solution
Step 1 — Work out nums.at(-2):
at() accepts negative positions and counts from the end: at(-1) is the last element, 50, so at(-2) is the one before it, 40.
Step 2 — Work out nums[nums.length - 2]:
nums.length is 5, so nums.length - 2 is 3, and nums[3] is three steps from the start — 10, 20, 30, then 40.
Step 3 — Compare them: Both land on the same element by two different routes, one counting backward from the end and one counting forward from the start.
Answer: Both return 40. at(-2) says "second from the end" directly; nums[nums.length - 2] says "index 3", computed as 5 - 2. The bracket form is the older way of writing it, and at() is the shorter one — note that nums[-2] is not an alternative, since -2 is simply an index that does not exist and gives undefined.
3.3.6 Name the four methods that add or remove at an end of an array, and say which end each one works on.
Solution
Step 1 — Sort them by which end they work on:
Two work at the end of the array: push and pop. Two work at the start: unshift and shift.
Step 2 — Sort them by add or remove:
Within each pair, one adds and one removes. push(value) adds at the end; pop() removes from the end. unshift(value) adds at the start; shift() removes from the start.
Step 3 — Note what the removers give back:
pop() and shift() both return the element they removed, so you can capture it: let served = line.shift();.
Answer:
| Method | What it does |
|---|---|
push(value) |
adds at the end |
pop() |
removes from the end, and returns what it removed |
unshift(value) |
adds at the start |
shift() |
removes from the start, and returns what it removed |
The four cover every combination of which end and add or remove.
3.3.7 What does this print? Trace line after each statement.
▶ Press Run to see the output…
Solution
Step 1 — After let line = ["a", "b"];:
line is ["a","b"], length 2.
Step 2 — After line.push("c");:
push adds at the end, so line is ["a","b","c"], length 3.
Step 3 — After let gone = line.shift();:
shift removes from the start and returns what it removed. It removed "a", so gone holds "a" and line is ["b","c"], length 2. Everyone left moved up an index — "b" is now at index 0.
Step 4 — Read the two prints:
console.log(gone) prints a. console.log(line) prints the shortened array.
Answer: It prints a and then ["b","c"]. Traced: ["a","b"] → ["a","b","c"] after the push → ["b","c"] after the shift, with the removed "a" captured in gone. Note that shift took from the opposite end to push, which is what makes this pair behave like a waiting line rather than a stack.
3.3.8 This loop prints one extra line, and the last thing it prints is undefined. Say why, and give the corrected loop header.
let arr = [5, 6, 7];
for (let i = 0; i <= arr.length; i++) {
console.log(arr[i]);
}
Write the corrected version in the editor and run it to confirm the extra line is gone.
▶ Press Run to see the output…
Solution
Step 1 — Count the rounds the loop actually runs:
arr has three elements, so arr.length is 3. The condition is i <= arr.length, which is true for i equal to 0, 1, 2, and 3 — four rounds.
Step 2 — Work out what the fourth round reads:
The valid indexes are 0, 1, 2. On the fourth round i is 3, so the body evaluates arr[3], which is past the end. That is not an error; it is undefined, and console.log dutifully prints it.
Step 3 — Fix the condition:
The loop should stop before length, not at it. Changing <= to < makes the last round run with i equal to 2, which is the last real index.
▶ Press Run to see the output…
Output:
5 6 7
Answer: The loop runs four times instead of three because i <= arr.length is still true when i is 3, and arr[3] does not exist, so the fourth line prints undefined. The corrected header is for (let i = 0; i < arr.length; i++). This is the classic off-by-one error, and the cure is to say the condition aloud as a sentence: "keep going while i is a real index."
3.3.9 When would you choose a for...of loop over a counting for loop, and when could you not?
Solution
Step 1 — Say what each loop hands you:
for...of hands you the value of each element, one per round. A counting for loop hands you the index, and you fetch the value yourself with arr[i].
Step 2 — Pick the case where for...of wins:
When the body only needs the values, for...of is shorter and has no counter, no condition, and therefore no off-by-one to get wrong. Printing every name, adding up every price, testing every temperature — all of these want for...of.
Step 3 — Pick the cases where it cannot do the job:
Two things for...of cannot give you. It does not tell you where you are, so any body that needs the position — "Score 0: 88", or comparing an element to its neighbour — needs the counting form. And it hands you a copy of each value rather than a way back into the slot it came from, so you cannot modify elements in place through it; arr[i] = … needs the i.
Answer: Choose for...of whenever the body needs only the values — it is shorter and cannot run off the end. You could not use it when you need the element's position (printing an index, comparing neighbours) or when you want to change elements in place, because for...of gives you a copy of the value with no route back to the slot. Both loops visit every element; the choice is decided by what the body needs, not by preference.
3.3.10 Why does a running total have to be set to 0 before the loop rather than inside it?
Solution
Step 1 — Work out what "inside the loop" would mean:
Statements inside the loop body run once per round. So let total = 0; placed inside would reset total to 0 at the start of every single round, throwing away everything added so far.
Step 2 — Trace the damage:
With [4.5, 2.25, 8.25], the loop would set total to 0, add 4.5, then reset to 0, add 2.25, then reset to 0 and add 8.25. After the loop you would have 8.25 — the last price, not the total.
Step 3 — Say why it cannot simply be left out:
Declaring it before the loop but with no value is no better. total would be undefined, and undefined + 4.5 is NaN, which then poisons every later addition.
Answer: A running total has to be set to 0 before the loop because the loop body runs once per element — setting it inside would wipe the accumulated value on every round and leave you with only the last element. Setting it before the loop gives the additions something to build on, and setting it to 0 specifically (rather than leaving it undefined) keeps the first addition a real number instead of NaN. This is the accumulator shape: declare before, change inside, use after.
3.3.11 Write a function smallest(numbers) that returns the lowest number in an array. Explain why starting from numbers[0] is safer than starting from 0.
▶ Press Run to see the output…
Solution
Step 1 — Reuse the shape from highest:
Hold a "best so far" in a variable, walk every element, and replace the best whenever you find something better. For the smallest, "better" means lower, so the comparison flips from > to <.
Step 2 — Choose the starting value:
Start best at numbers[0] — a real element from the list.
Step 3 — Return it after the loop, not inside:
The answer is only known once every element has been checked, so the return goes after the loop closes.
▶ Press Run to see the output…
Output:
3 -9 7
Answer: Starting from numbers[0] is safer than starting from 0 because 0 is not necessarily in the list. Watch the second call: every temperature there is below freezing, and none of them is lower than 0, so a function starting at best = 0 would never replace it and would answer 0 — a number that was never in the array. Beginning with a real element guarantees the answer is one of the values you were actually given.
3.3.12 Write a function longWords(words) that returns a new array holding only the words with more than four characters. (Hint: word.length works on a string too.)
▶ Press Run to see the output…
Solution
Step 1 — Recognise the pattern: This is the build-a-new-array shape from Example 3.3.3 — make an empty array, loop, push what qualifies, return it.
Step 2 — Write the test:
word.length works on a string just as it does on an array, counting characters instead of elements. "More than four characters" is word.length > 4, so a four-letter word does not qualify.
Step 3 — Return result after the loop:
▶ Press Run to see the output…
Output:
["elephant","giraffe"] []
Answer: Build an empty result, loop over words with for...of, push each word whose length is greater than 4, and return result. "bird" is excluded because four is not more than four — the boundary is where this kind of function usually goes wrong. When nothing qualifies the function returns [], an empty array rather than undefined, so the caller can loop over the result without checking first.
3.3.13 Given let matrix = [[1, 2], [3, 4], [5, 6]];, what do matrix[2][0] and matrix.length return?
Solution
Step 1 — Read matrix[2][0] left to right:
matrix[2] picks the element two steps from the start of the outer array, which is the third inner array, [5, 6]. Then [0] takes that inner array's first element, 5.
Step 2 — Read matrix.length:
The outer array holds three elements, and each one happens to be an array. length counts those outer elements, so it is 3.
**Step 3 — Notice what length does not count:**
There are six numbers in the grid, but matrix.length is not 6. The outer array knows only how many rows it holds; it knows nothing about how long any row is. To count a row you would ask matrix[0].length.
Answer: matrix[2][0] returns 5 and matrix.length returns 3. The 3 is the number of rows, not the number of numbers — a nested array's length describes only its own top level.
3.3.14 A function is given an array and pushes a value onto it. Will the caller see that change? Answer from what you saw in Section 3.3.6, and say which section explains the rule in full.
Solution
Step 1 — Recall what Section 3.3.6 showed: That section's Context Pause draws the line: a number handed to a function is copied, so the function cannot change the caller's copy. An array is not copied — the function receives a way back to your array.
Step 2 — Apply it to a push:
Because the function is holding a route back to the caller's array rather than a copy of it, a push inside the function adds to the very same array the caller is holding. There is only ever one array involved.
Step 3 — Note the way around it:
Example 3.3.3 sidesteps this deliberately by building a brand-new result array and leaving the input untouched. That is the habit to keep: if a function should not disturb its caller's data, have it build and return something new rather than modify what it was handed.
Answer: Yes — the caller will see the pushed value, because an array is not copied when it is passed to a function; the function receives a way back to the caller's own array. Section 3.6 explains the rule in full, under pass by value versus pass by reference.
Key Terms
Array -- An ordered collection of values stored under a single name, written with square brackets.
Element -- One value inside an array.
Index -- The position of an element, counting from 0; read it as how far from the start.
length -- The number of elements in an array; the last index is always length - 1.
push / pop -- Add to the end of an array, and remove from the end returning what was removed.
unshift / shift -- Add to the front of an array, and remove from the front returning what was removed.
at() -- Reads an element, accepting negative positions so at(-1) is the last element.
for...of loop -- A loop that runs once per element and hands you the value, with no counter to get wrong.
Off-by-one error -- Running a loop one round too many or too few, usually from <= where < was meant.
Accumulator -- A variable set before a loop and updated inside it, holding a running total or a list being built.
Two-dimensional array -- An array whose elements are themselves arrays, used for grids and tables.