Array basics
Create JavaScript arrays, read indexes with at() and length, change both ends with push, pop, shift, and unshift, and avoid sparse-array surprises.
- 01Make the array you meanMake arrays with square brackets, and know why new Array(3) gives three empty positions instead of the number 3.
- 02Read by positionRead elements with indexes that start at 0, read the last one with at(-1), and use length to make an array shorter.
- 03Change an array on purposePredict what push, pop, shift, and unshift do and return, and spot extra properties and holes.
Arrays are ordered lists
An array is a list of values kept in order. You can read any value by its position. You can also pass the whole list around under one name. Many everyday things are lists in order: the items in a shopping cart, the results of a search, and the answers in a quiz.
An array is a special kind of object that keeps values in order. Each value in the list is called an element. Each element sits at a numbered position, called an index. The first index is 0.
An array also has a length property. It is one more than the highest index. For a normal list, that is the number of elements.
const cart = ["tea", "bread"];
console.log(cart[0]);
console.log(cart.length);Line 1 makes an array named cart with two elements. Line 2 reads index 0, the first position, so it prints tea. Line 3 reads the array's length, so it prints 2. The elements stay in their order, and the whole list has one name.
cart points at one row of values. The first position is index 0, the next is index 1. There are two values, so cart.length is 2.Picture a hallway with a row of lockers. Each locker has a number painted on it. The numbers start at 0, so the first locker is locker 0 and the second is locker 1. The last locker's number is always one less than the number of lockers.
- In real life: Locker 0, locker 1, locker 2
- In JavaScript: Indexes
0,1,2 - In real life: The thing inside a locker
- In JavaScript: The element stored at that index
- In real life: How many lockers there are
- In JavaScript:
length: the last index plus one - In real life: Taking lockers away from the end
- In JavaScript: Setting a smaller
lengthremoves elements from the end
This lesson uses ideas from earlier lessons:
- Data types: there,
typeof []gave"object". - Objects & references: two names can point at the same object.
- Object basics: how named properties work.
- Loops and
for…of&for…in: there you learned not to usefor…into read array values. - Manuals & specifications: it used
.at()as an example entry. Now you will use it for real.
Two ways to make an array
STEP THROUGHThe usual way to make an array is an array literal: square brackets with the values inside, like ["Ada", "Grace"]. It is clear and safe.
There is also a function called Array(). You call it with the word new, like new Array(3). A function you call with new to make an object is called a constructor. It has one well-known trap: new Array(3) does not store the number 3. It makes an array whose length is 3, with nothing inside.
const cart = ["tea"];
const emptySlots = new Array(2);
console.log(cart.length);
console.log(emptySlots.length, 0 in emptySlots);Line 1 makes an array with one real element, tea. Line 2 makes an array with two empty positions. Line 3 prints 1. Line 4 prints 2 false: the length is 2, but nothing is stored at index 0.
The in operator on line 4 asks a yes-or-no question. 0 in emptySlots means "is something stored at index 0 of emptySlots?" Here the answer is false. When you already know the values, use square brackets.
new Array(2) puts nothing in. It only sets length to 2, so both positions are empty.Guess what each line makes before you step. The tricky one is new Array(3): it is not the same as [3].
script
const threeHoles = new Array(3);const twoValues = new Array(1, 2);const oneFromOf = Array.of(3);const withHole = [1, , 3];console.log(oneValue.length, 0 in oneValue);console.log(threeHoles.length, 0 in threeHoles);console.log(twoValues.join("-"));console.log(oneFromOf[0]);console.log(1 in withHole);Commas need care too. A comma after the last value, as in [1, 2,], is allowed and adds nothing. Two commas in a row, as in [1, , 3], skip a position. Index 1 is then a hole: a position with nothing stored in it.
Two more ways to make arrays, Array.of() and Array.from(), come back in the next lesson, Slicing, splicing & joining. For now, square brackets are the best choice.
[3]new Array(3)new Array(1, 2)Array.of(3)[1, , 3][1, undefined, 3]
Sort each line of code into one of two groups: it makes real values, or it leaves holes. Each card explains why.
Reading by position, and what length means
INTERACTIVEAn index is a position number. Square brackets after the array's name read a position counted from the start: arr[0] is the first element.
The at() method reads a position too. arr.at(0) is also the first element. But at() also takes negative numbers, which count from the end. So arr.at(-1) is the last element.
If you ask for a position that does not exist, you get undefined. There is no error.
Change the index, guess each read, then step through. Watch length = 2 make the real array shorter.
script
console.log(languages.at(0));console.log(languages.at(-1));console.log(languages[languages.length - 1]);console.log(languages[10]);console.log(languages.at(-10));languages.length = 2;console.log(languages);const scores = [8, 13, 21];
console.log(scores[0]);
console.log(scores.at(-1));
console.log(scores.at(10));Line 2 reads index 0, the first score: 8. Line 3 uses at(-1) to read the last score: 21. Line 4 asks for index 10. The array has only three elements, so it prints undefined.
length is a property, not a method, so you write it without round brackets: arr.length. Most of the time it is the number of elements in the list. The exact rule is: length is one more than the highest index.
You can also set length yourself:
- Set it smaller, and the elements past the new end are removed.
- Set it larger, and the new positions are holes.
When you mean "the last element", write arr.at(-1). It says what you mean, and you don't have to write arr[arr.length - 1]. When you already have a position that is 0 or more, square brackets are fine.
Adding and removing at the ends
LIVE LABYou can change an array after you make it. The first four methods to learn all work at one end of the list:
push(value)adds a value at the back. It returns the new length.pop()removes the last value. It returns the value it removed.unshift(value)adds a value at the front. It returns the new length.shift()removes the first value. It returns the value it removed.
unshift() and shift() work at the front, where index 0 is. push() and pop() work at the back, after the last value.Think of a stack of plates. You put a new plate on top, and you take the top plate off. Nothing else moves. That is like the back of an array.
Now think of people waiting in a line. When someone joins or leaves at the front, everyone behind them moves one place. Their place numbers all change. That is like the front of an array.
- In real life: Put a plate on top
- In JavaScript:
push(value)adds at the back - In real life: Take the top plate off
- In JavaScript:
pop()removes from the back - In real life: Someone joins the front of the line
- In JavaScript:
unshift(value)adds at the front - In real life: The first person leaves the line
- In JavaScript:
shift()removes from the front
const items = ["Ada", "Grace", "Linus"];items.push(value);items.pop();items.unshift(value);items.shift();items[5] = value;items.length = 2;- returned
- —
- last line run
const items = ["Ada", "Grace", "Linus"];
The array starts with three names. Pick a button. Guess what it returns, then watch the boxes change.
const queue = ["Asha", "Ben"];
console.log(queue.push("Chen"));
console.log(queue.pop());
console.log(queue);Line 2 runs push, which adds Chen at the back. It prints what push returns: the new length, 3. Line 3 runs pop, which removes the last value and returns it, so it prints Chen. Line 4 prints what is left: ["Asha", "Ben"].
The lab has two more buttons:
items[5] = valuewrites far past the end. The length jumps to 6, and the positions in between become holes.items.length = 2makes the array shorter. Every element after index1is removed.
Arrays are objects
STEP THROUGHAn array is a special kind of object. That means:
- Two names can point at the same array, just like with any object.
- You can add ordinary named properties to an array.
- Its index numbers are really property names, stored as strings like
"0". typeof []gives"object", not "array".
To check whether a value is an array, use Array.isArray(value). It returns true for an array and false for anything else.
An array works like an object, with extra rules for elements and length.
script
tools.label = "toolbox";console.log(typeof tools);console.log(Array.isArray(tools));console.log(tools.length);console.log(tools[0] === tools["0"]);console.log(JSON.stringify(Object.keys(tools)));const profile = ["Asha"];
profile.label = "team";
console.log(Array.isArray(profile));
console.log(profile.length);
console.log(profile.label);Line 2 adds an ordinary property, label. Line 3 prints true, because profile is an array. Line 4 prints 1: the label is not an element, so the length does not change. Line 5 reads the label like any property and prints team.
The table compares the two kinds of data an array can hold. Read each row as a question.
| Question | An element | A named property |
|---|---|---|
| What does it look like? | arr[0] = "Ada" | arr.label = "team" |
Does it change length? | Yes, when it is at or past the current end. | No. |
| Do array methods use it? | Yes. Methods like map and pop work with elements. | Usually not. |
| What is its key? | A string that looks like a number, such as "0". | Any property name, such as "label". |
This is why for…in is the wrong loop for reading array values. It walks through property names, so it can also pick up extra properties like label. Use for…of to read the values. Later lessons teach array methods for this too: Searching arrays, map, filter & reduce, and Sorting & copying safely.
Holes and sparse arrays
STEP THROUGHA hole is a position with nothing stored in it. An array with holes is called a sparse array. A hole is different from a position that stores the value undefined. When you read either one, you get undefined.
The in operator shows the difference. 1 in arr is true only when something is really stored at index 1.
undefined. Reading either one gives undefined, but only the in check tells them apart.Step slowly. A hole has nothing stored in it; it is not a hidden undefined. Most code should not make holes.
script
const explicit = [1, undefined, 3];console.log(1 in holey);console.log(1 in explicit);const grown = ["a", "b"];grown[5] = "x";console.log(grown.length, 2 in grown, 5 in grown);console.log(holey.map((value) => value * 2));for (const value of holey) console.log(value);console.log(Array.from({ length: 3 }));const todo = ["read", , "ship"];
console.log(1 in todo);
console.log(todo[1]);Line 1 skips index 1, so it is a hole. Line 2 prints false, because nothing is stored at index 1. Line 3 reads index 1 and still prints undefined. So reading a position cannot tell you whether something is stored there.
The table compares a hole with a stored undefined. Read across each row.
| Question | Hole: [1, , 3] | Stored: [1, undefined, 3] |
|---|---|---|
| Is something stored at index 1? | No. 1 in array is false. | Yes. 1 in array is true. |
| What does reading index 1 give? | It gives undefined. | It gives undefined. |
Do forEach and map visit index 1? | No. They skip holes. | Yes. They visit it like any element. |
| Should you make it on purpose? | Almost never. | Sometimes, when undefined has a meaning in your code. |
The simple advice: don't make holes in everyday code. If you need empty places, put real values there, such as null, undefined, or an object that says what is missing. A later lesson, Fast arrays & elements kinds, shows how holes can also make code slower.
Where you’ll use this
Use an array whenever your data has an order. Two examples:
- A web page keeps a list of notifications. When a new one arrives, it adds it with
push. To show the newest one, it readsnotifications.at(-1). - A text editor keeps a list of undo steps. It adds each action with
push, and undoes the newest action withpop.
const cart = ["tea"];
cart.push("bread");
console.log(cart.at(-1));
console.log(cart.length);The cart starts with one item. Line 2 uses push to add bread. Line 3 reads the last item with at(-1) and prints bread. Line 4 prints the length, 2. A shopping site does the same thing when you add an item to your cart.
Here are more places where arrays fit well:
- Queues: a list where the first one in is the first one out. Examples: people waiting for help, messages waiting to send.
- Stacks: a list where the last one in is the first one out. Examples: undo history, the pages behind the Back button, dialogs opened on top of each other.
- Rows of data: products, table rows, search results, points on a chart.
- Changing every value: later lessons teach
map,filter, andreduce.
Use an array when the order matters, or when the same value can appear twice. Use an object when you look things up by name. The later lesson Choosing a data structure helps you decide step by step.
Common misconceptions
“new Array(3) is the same as [3].”
No. new Array(3) makes an array with length 3 and three holes. To store the number 3, write [3] or Array.of(3).
“length counts the values.”
Not exactly. length is one more than the highest index. Holes still count toward it, even though nothing is stored there.
“push returns the item I pushed.”
No. push and unshift return the new length. pop and shift return the value they removed.
“A hole is just undefined.”
Reading a hole gives undefined, but nothing is stored at that index. The in operator tells the two apart.
“Arrays are not objects.”
They are a special kind of object. That is why named properties work on them, and why two names can point at one array.
const emptySlots = new Array(2);
const realUndefined = [undefined, undefined];
console.log(0 in emptySlots);
console.log(0 in realUndefined);Reading index 0 gives undefined for both arrays. But line 3 prints false, because emptySlots has nothing stored at index 0. Line 4 prints true, because realUndefined stores undefined there. Use in when "nothing stored" and "stored undefined" must mean different things.
Practice: array basics
5 EXERCISESPredict the number that length prints after the three changes.
const queue = ["Ada", "Grace"];
queue.push("Linus");
queue.unshift("Edsger");
queue.pop();
console.log(queue.length);After line 4 the array is ["Edsger", "Ada", "Grace"], so line 5 prints 3.
An undo stack keeps actions in a list. Undo removes the newest one. The code uses push and pop to do this. What two lines print?
const undoStack = [];
undoStack.push("typed heading");
undoStack.push("added image");
const lastAction = undoStack.pop();
console.log(lastAction);
console.log(undoStack.length);const undoStack = [];
undoStack.push("typed heading");
undoStack.push("added image");
const lastAction = undoStack.pop();
console.log(lastAction);
console.log(undoStack.length);The newest action is added image, so pop() returns it. One action is left in the stack, so the length is 1.
The code reads the last score with at(-1). What prints?
const scores = [8, 13, 21];
console.log(scores.at(-1));const scores = [8, 13, 21];
console.log(scores.at(-1));scores.at(-1) reads the last value, 21. You don't have to write scores.length - 1.
A badge list should hold three real placeholder strings, not holes. The fixed code uses Array.from(). It makes an array of the given length and fills each position with what the arrow function returns. After the fix, what does line 3 print?
const badges = Array.from({ length: 3 }, () => "new");
console.log(badges.length);
console.log(0 in badges);const badges = Array.from({ length: 3 }, () => "new");
console.log(badges.length);
console.log(0 in badges);The fixed code makes three real values, so something is stored at index 0 and 0 in badges prints true.
The code uses the in operator to check whether something is stored at index 1. What prints?
const items = ["first", , "third"];
console.log(1 in items);const items = ["first", , "third"];
console.log(1 in items);The two commas in a row leave a hole at index 1, so 1 in items is false.
Quiz: check your understanding
7 QUESTIONSAnswer each question from memory first. Then read the explanation for every choice.
Question 1 of 7Which line of code makes an array that holds one value, the number 3?
Choose an answer to see the explanation.
Question 2 of 7What does at(-1) print here?
Read the code, then predictconst letters = ["a", "b", "c"]; console.log(letters.at(-1));Choose an answer to see the explanation.
Question 3 of 7What do push and length print here?
Read the code, then predictconst list = ["x", "y"]; console.log(list.push("z")); console.log(list.length);Choose an answer to see the explanation.
Question 4 of 7Which method removes the first element of an array and returns it?
Choose an answer to see the explanation.
Question 5 of 7What length prints after adding arr.label?
Read the code, then predictconst arr = ["a", "b"]; arr.label = "letters"; console.log(arr.length);Choose an answer to see the explanation.
Question 6 of 7What do the two in checks print?
Read the code, then predictconst holey = [1, , 3]; const explicit = [1, undefined, 3]; console.log(1 in holey); console.log(1 in explicit);Choose an answer to see the explanation.
Question 7 of 7Why are shift and unshift usually slower than push and pop on very large arrays?
Choose an answer to see the explanation.
Key takeaways
- Arrays keep values in order, at indexes that start at
0. - Make arrays with square brackets.
new Array(3)makes three holes;[3]stores one value. at(-1)reads the last element. Setting a smallerlengthremoves elements from the end.pushandpopwork at the back.unshiftandshiftwork at the front, where every other element has to move.- Arrays are objects. A hole is a position with nothing stored in it. Avoid holes unless you have a clear reason.
Remember the one-liner.
An array is a special object that keeps a list of values in order, starting at index 0. Keep every position filled, and length tells you where the list ends.
Up next: Slicing, splicing & joining.