Arrays And Objects
Array
Problem Statement
We've talked about data types in JavaScript. But what if we need a way of organizing data? We'll need to reach for a data structure, and one of the most useful data structures is an Array
.
Objectives
Identify data structures and
Array
sCreate
Array
sAccess the elements in an
Array
Add elements to an
Array
Remove elements from an
Array
Replace elements in an
Array
Identify nested
Array
s
Identify Data Structures and Arrays
A data structure is a means for associating and organizing information. Outside of the programming world, we use data structures all the time. For example, we might have a shopping list of the items we need to buy on our next grocery run or an address book for organizing contact information.
If we have a lot of related data, it's best to represent it in a related system. Imagine that we're working on a lottery application that has to represent the winning lottery numbers. We could do that as follows:
We've represented all six pieces of data, but they aren't related in any meaningful way. Every single time we want to reference that combination of winning numbers, we need to remember and type out six different variable names:
That's so much typing! There are much, much better ways to keep organize data in JavaScript. Let's learn about one of the most common: the Array
.
Create Arrays
An Array
is a list, with the items listed in a particular order, surrounded by square brackets ([]
):
The members or elements in an Array
can be data of any type in JavaScript:
NOTE: In some other languages
Arrays
cannot be of multiple types. In C, C++, Java, Swift, and others you cannot mix types. JavaScript, Python, Ruby, Lisp, and others permit this.
Arrays are ordered, meaning that the elements in them will always appear in the same order. The Array
[1, 2, 3]
is different from the Array
[3, 2, 1]
.
Just like any other type of JavaScript data, we can assign an Array
to a variable:
We can find out how many elements an Array
contains by checking the Array
's built-in length
property:
We defined the above Array
s using the array literal syntax — that is, we literally typed out the Array
that we wanted to create, square brackets and all. There are other ways to create new Array
s, but they are only necessary for very rare circumstances. For now, use Array
literals.
To get a sense of just how effective Array
s are at keeping data organized, let's rewrite our lottery code to use an Array
:
The Array
provides organization, and we only have to remember one identifier (winningNumbers
) instead of six (firstNumber
, secondNumber
, and so on). We can also call Arrays
expressive because putting all the winning numbers in a shared data structure communicates to other programmers "Hey, these things go together" in a way that firstNumber
, secondNumber
, etc. does not.
The one benefit of storing all six lottery numbers separately is that we had a really easy way to access each individual number. For example, we could just reference powerBall
to grab the sixth number. Luckily, Array
s offer an equally simple syntax for accessing individual members.
Access the Elements in an Array
Every element in an Array
is assigned a unique index value that corresponds to its place within the collection. The first element in the Array
is at index 0
, the fifth element at index 4
, and the 428th element at index 427
.
To access an element, we use the computed member access operator, which, conveniently enough, looks exactly like an Array
:
NOTE: Most people just call it bracket notation or the bracket operator, so don't worry too much about remembering the term computed member access operator.
Let's take a minute to think about how we could access the last element in any Array
.
If myArray
contains 10 elements, the final element will be at myArray[9]
. If myArray
contains 15000 elements, the final element will be at myArray[14999]
. So the index of the final element is always one less than the number of elements in the Array
. If only we had an easy way to figure out how many elements are in the Array
...
This is why it's called the computed member access operator. We put an expression (alphabet.length - 1
) inside the square brackets, and the JavaScript engine computed the value of that expression to determine which element we were trying to access. In this case, alphabet.length - 1
evaluated to 25
, so alphabet[alphabet.length - 1]
became alphabet[25]
.
Add Elements to an Array
JavaScript allows us to manipulate the members in an Array
in a number of ways.
.push()
and .unshift()
.push()
and .unshift()
With the .push()
method, we can add elements to the end of an Array
:
We can also .unshift()
elements onto the beginning of an Array
:
Notice that the value returned by both methods is the length
of the updated Array
.
Destructive vs. Nondestructive
Both .push()
and .unshift()
update or mutate the original Array
, adding elements directly to it. Operations that modify the original collection are destructive, and those that leave the original collection intact are nondestructive.
Mutating the original Array
isn't necessarily a bad thing, but there's also a way to add elements nondestructively, leaving the original Array
intact.
Spread Operator
ES2015 introduced the spread operator, which looks like an ellipsis: ...
. The spread operator allows us to spread out the contents of an existing Array
into a new Array
, adding new elements but preserving the original:
We created a new Array
instead of modifying the original one — our coolCities
Array
was untouched. We can also use the spread operator to add a new item to the end of an Array
without modifying the original:
Remove Elements from an Array
As complements for .push()
and .unshift()
, respectively, we have .pop()
and .shift()
.
.pop()
and .shift()
.pop()
and .shift()
The .pop()
method removes the last element in an Array
, destructively updating the original Array
:
The .shift()
method removes the first element in an Array
, also mutating the original:
Notice that the return value for the .pop()
and .shift()
methods is the element that was removed.
.slice()
.slice()
To remove elements from an Array
nondestructively (without manipulating the original Array
), we can use the .slice()
method. Just as the name implies, the .slice()
method returns a portion, or slice, of an Array
.
With No Arguments
If we don't provide any arguments, .slice()
will return a copy of the original Array
with all elements intact:
Note that the Array
returned by .slice()
has the same elements as the original, but it's a copy — the two Array
s point to different objects in memory. If you add an element to one of the Array
s, it does not get added to the other:
With Arguments
We can provide two arguments to .slice()
, the index where the slice should begin and the index before which it should end:
If no second argument is provided, the slice will run from the index specified by the first argument to the end of the Array
:
To remove the first element and return a new Array
, we call .slice(1)
:
And we can remove the last element in a way that will look familiar from earlier in this lesson:
In fact, .slice()
provides an easier syntax for grabbing the last element in an Array
:
When we provide a negative index, the JavaScript engine knows to start counting from the last element in the Array
instead of the first.
.splice()
.splice()
The documentation shows three ways to use .splice()
:
With a Single Argument
The first argument expected by .splice()
is the index at which to begin the splice. If we only provide the one argument, .splice()
will destructively remove a chunk of the original Array
beginning at the provided index and continuing to the end of the Array
:
Notice that .splice()
returns the removed chunk and leaves the remaining elements in the original Array
.
With a negative 'start' index, the opposite happens:
With Two Arguments
When we provide two arguments to .splice()
, the first is still the index at which to begin splicing, and the second dictates how many elements we want to remove from the Array
. For example, to remove 3
elements, starting with the element at index 2
:
Replace Elements in an Array
.splice()
with 3+ arguments
.splice()
with 3+ argumentsAfter the first two, every additional argument passed to .splice()
will be inserted into the Array
at the position indicated by the first argument. We can replace a single element in an Array
as follows, discarding a card and drawing a new one:
Or we can remove two elements and insert three new ones as our restaurant expands its vegetarian options:
We aren't required to remove anything with .splice()
— we can use it to insert elements anywhere within an Array
. Here we're adding new books to our library in alphabetical order:
Notice that .splice()
returns an empty Array
when we provide a second argument of 0
. This makes sense because the return value is the set of elements that were removed, and we're telling it to remove 0
elements.
Keep playing around with .splice()
in your browser's console to get comfortable with it.
Using the Computed Member Access Operator to Replace Elements
If we only need to replace a single element in an Array
, there's a simpler solution than .splice()
:
However, using the computed member access operator ([]
) is still destructive — it modifies the original Array
. There's a nondestructive way to replace or add items at arbitrary points within an Array
, and it involves two of the concepts we learned earlier.
Slicing and Spreading
Combining .slice()
and the spread operator allows us to replace elements nondestructively, leaving the original Array
unharmed:
Play around with this a bit until it makes sense. It's the trickiest thing that we've encountered in this lesson, so don't sweat it if it takes a little while to sink in!
Identify Nested Arrays
In the above 'slicing and spreading' example, if we don't use the spread operator we're left with an interesting result:
Holy nested Array
s, Batman!
That's right — an Array
can contain elements of any data type, including other Array
s:
Pop that into your browser's JS console and check out the nesting:
It's great that Array
s allow us to store other Array
s inside them, but this is a terrible way to represent a deeply nested data structure. In general, try to keep your Array
s to no more than two levels deep. Two levels is perfect for representing two-dimensional things like a tic-tac-toe board:
The cool thing about representing a game board like that is in how we can access the different squares by specifying coordinates. The first []
operator grabs the row that we want, top (board[0]
), middle (board[1]
), or bottom (board[2]
). For example:
The second []
operator specifies the square within that row, left (board[1][0]
), middle (board[1][1]
), or right (board[1][2]
). For example:
Effectively, we're using X and Y coordinates to refer to data within a two- dimensional structure.
Conclusion
We dove into data structures and the Array
, including how to create Array
s, access elements in an Array
, add elements to an Array
, remove elements from an Array
and replace elements in an Array
. We also covered the difference between destructive and non-destructive Array
manipulation.
Resources
MDN
Last updated