You'll be coding along in
arrays.js. There are tests to run to make sure you're on the right track.
Let's say that we have a list of ingredients for a kickin' grilled cheese (code along in console):
var ingredient1 = "bread" var ingredient2 = "mild cheese" var ingredient3 = "sharp cheese" var ingredient4 = "butter" var ingredient5 = "tomato" var ingredient6 = "garlic"
But now what if we want to make a tomato sauce? Well, we already have garlic and tomato — but we have no idea what recipe they belong to. Pretty soon, we'll have a hard time keeping our ingredients safe, and we'd end up with bread in our tomato sauce.
This is an admittedly contrived example, but it goes to show that we can't just put everything in a variable and hope to remember what order things should go in. It also shows that sometimes it would be helpful to be able to group like items together.
Arrays look like this:
[1, 2, 3].
Or like this:
var grilledCheeseIngredients = [ 'bread', 'mild cheese', 'sharp cheese', 'butter', 'tomato', 'garlic' ] var tomatoSauceIngredients = [ 'tomato', 'garlic', 'olive oil', 'basil', 'oregano' ]
var myArray = [element0, element1, ..., elementN];
var primeNumbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]; var tvShows = ["game of thrones", "true detective", "the good wife", "empire"]; var weirdGreeting = [ "he", 110, "w", 0, "r", 1, "d" ]; var empty = ;
The Array constructor is another approach to making a new array.
var evenNumbers = new Array();
Arrays are ordered, meaning that the elements in them will always appear in the same order. The array
[1, 1, 2], is different from the array
[1, 2, 1].
arrays.js, define a variable called
chocolateBars. Its value should be an array of the strings
push elements onto the end of an array:
var superheroines = ["catwoman", "she-hulk", "mystique"]; superheroines.push("wonder woman"); // superheroines is now ["catwoman", "she-hulk", "mystique", "wonder woman"]
We can also
unshift elements onto the beginning of an array:
var cities = ["New York", "San Francisco"] cities.unshift("Philadelphia") // cities is now ["Philadelphia", "New York", "San Francisco"]
These actions change the underlying array — in other words, they mutate its value.
Most modern browsers (Chrome, FireFox, and Safari) support what is called the spread operator — it's three dots in a row:
.... When used with an array, it spreads out the array's contents.
We can use the spread operator to create a new array in place, rather than modifying the original one. Let's try it!
var cities = ["New York", "San Francisco"] ["Philadelphia", ...cities] // ["Philadelphia", "New York", "San Francisco"] cities // ["New York", "San Francisco"]
Whoa! Did you see that? Our cities array was untouched when we used the spread operator:
...cities. We can do the same at the beginning of the array:
var cities = ["New York", "San Francisco"] [...cities, "Philadelphia"] // ["New York", "San Francisco", "Philadelphia"]
To preserve the new array, we need to assign it to a variable:
var cities = ["New York", "San Francisco"] // we can assign it to the existing `cities` variable cities = ["Philadelphia", ...cities] // but if we have a const const cats = ["Milo", "Garfield"] // we need a new variable: const moreCats = ["Felix", ...cats]
While we can add elements to an array directly at specific indexes
var myArray = [1, 2, 3] myArray = 5 myArray // [1, 2, 3, undefined, undefined, 5]
it's best not to. We should treat arrays as ordered lists of information that can be any length, so updating a specific index should feel like a weird thing to do. Moreover, adding elements directly inserts
undefined (as demonstrated above) if we also need to increase the array's length, which can lead to unexpected behavior.
arrays.js, define two functions,
destructivelyAddElementToBeginningOfArray. Both functions take two parameters, an array and an element to add to the beginning of the array, and both functions should add the element to the beginning of the array and then return the whole array. The destructive function,
destructivelyAddElementToBeginningOfArray, should alter the original array that's passed in;
addElementToBeginningOfArray, on the other hand, should return a new array and not modify the original.
TODO: Define two more functions,
destructivelyAddElementToEndOfArray. These functions also take two arguments, an array and an element to add to the end of the array.
addElementToEndOfArray should not alter the original array;
destructivelyAddElementToEndOfArray should alter the original array.
You can get elements out of arrays if you know their index. Array elements' indexes start at 0 and increment by 1, so the first element's index is
0, the second element's index is
1, the third element's is
var entrepreneurs = ["Oprah Winfrey", "Laurene Powell Jobs", "Arianna Huffington"]; // the line below will print the string "Oprah Winfrey" console.log(entrepreneurs); // the code below will print the string "Arianna Huffington is the co-founder and editress-in-chief of The Huffington Post" var bio = " is the co-founder and editress-in-chief of The Huffington Post"; console.log(entrepreneurs + bio); // the line below will return undefined entrepreneurs;
TODO: Define a function in
accessElementInArray. The function should accept an array and an index and return the element at that index.
To remove an element from the beginning of an array, we can use the
const days = ["Monday", "Tuesday", "Wednesday"] days.shift() // returns the removed element, in this case "Monday" days // ["Tuesday", "Wednesday"]
unshift, this method is destructive; it mutates the underlying array.
TODO: Define a function in
destructivelyRemoveElementFromBeginningOfArray that takes an array as its only argument and removes the first element. Your function should then return the entire array, and it should mutate the array.
Because we tend to want to avoid destruction, there is also a way to remove the first element from an array without changing the underlying array: we can use the
slice does just what its name implies: it takes a slice from its array. The first argument specifies where the slice starts, and the second argument specifies where it ends. If there is no second argument, the slice goes from the first argument (the start) to the end of the array. This means removing the first element is as simple as
var cats = ["Milo", "Garfield", "Otis"] cats.slice(1) // ["Garfield", "Otis"] cats // ["Milo", "Garfield", "Otis"]
As with other non-destructive methods, we need to assign the results to a new variable to save our changes:
var cats = ["Milo", "Garfield", "Otis"] cats = cats.slice(1) // ["Garfield", "Otis"] cats // ["Garfield", "Otis"]
slice is also handy if we know we want the last
n elements of an array: pass it a negative index.
var cats = ["Milo", "Garfield", "Otis"] // get the last 2 cats cats.slice(-2) // ["Garfield", "Otis"] // get the last 1 cat cats.slice(-1) // ["Otis"]
TODO: Define a function in
removeElementFromBeginningOfArray. It takes an
array as its only argument. The function should remove the first element in the array. This function should return the entire array in the same line, and it should not mutate the original array.
To remove an element from the end of an array, we can use the
var iceCreams = ["chocolate", "vanilla", "raspberry"] iceCreams.pop() // returns the removed element, in this case "raspberry" iceCreams // ["chocolate", "vanilla"]
push, this method is destructive; it mutates the underlying array.
TODO: Define a function in
destructivelyRemoveElementFromEndOfArray that takes an array as its only argument and removes the last element. Your function should return the entire array, and it should mutate the array.
We can use
slice to perform the above action without changing the underlying array. It takes a bit more work than removing the first element, since we want the slice from index
0 (remember, the first element is at index
0!) to the end. Hmmmm — what property do arrays have that can help us?
var iceCreams = ["chocolate", "vanilla", "raspberry"] iceCreams.slice(0, iceCreams.length - 1) // ["chocolate", "vanilla"] iceCreams // ["chocolate", "vanilla", "raspberry"]
TODO: Define a function in
removeElementFromEndOfArray that takes an array as its only argument and removes the last element. Your function should return the array without the last element, and it should not mutate the original array.
splice method, which takes an index in the array as its first argument, the number of elements to remove as its second argument, and any number of elements to add as any arguments after the second. All arguments are optional, but with no arguments,
splice() returns an empty array and does nothing to the target array.
It might be helpful to refer to MDN to check out their examples, in addition to our examples here.
let items = [1, 2, 3, 4] // this will remove everything after index 1 (inclusive) // it returns the removed items: [2, 3, 4] items.splice(1) items //  items = [1, 2, 3, 4] // "at index 1, remove 1 item" // it returns the removed item(s):  items.splice(1, 1) items // [1, 3, 4] items = [1, 2, 3, 4] // "at index 1, remove 1 item and add 6 and add 7" // it returns the removed items:  // and adds the items to add starting at the removal index items.splice(1, 1, 6, 7) items // [1, 6, 7, 3, 4]
As we noted above, adding elements at specific indexes in the middle of an array feels weird — it's intentionally difficult to do, as doing so with objects (where we have keys instead of sequential indexes) is much more natural.
We can use
slice, combined with the spread operator, to make removing from the middle of an array much easier.
var items = [1, 2, 3, 4, 5] // let's remove the third element // a slice from the start up to but not including index 2 (the third element) // and a slice from index 3 to the end [...items.slice(0, 2), ...items.slice(3)] // [1, 2, 4, 5]
Play around with this a bit until it makes sense. It's the trickiest thing that you've encountered so far, so don't sweat it if it takes a little bit to sink in!
If you had to guess, would you say that array indexes are numbers or strings? Think about it for a second, then read on.
Array indexes are actually strings, even though we commonly refer to them as numbers. But you don't have to take my word for it: try typing
Object.keys([1, 2, ,3]) in your console and see what comes back.
Ultimately, this means array indexes are strings that can be accessed by array-style notation using brackets, and the numbers will be coerced into strings when they're needed under the hood. In a console, try accessing an index using a string to see for yourself:
var arr = ["under", "the", "hood"]; arr; // "under" arr['0']; // "under" arr; // 02 the number *is* 2, so you get "hood" arr['02']: // '02' the string is *not* 2, so you get undefined
This little tidbit might come in handy if you ever try to assign a value to an array index by using a string unintentionally. Like, say, by getting your array positions from a zero-filled formatted list of numbers which you store as strings, then using those strings to access array elements.
Or by indexing an array with a variable whose contents don't in any way represent a number--like typing
myArray['bonobo monkey'] = 27.
You'll get no complaints, because rather than adding an index to the array, you're adding a property. Speaking of which...
A property is a named piece of information. They're kind of like variables (don't go too far with that analogy) but we can only get that information with reference to the property owner.
What makes arrays special, then? Arrays keep track of how many elements they have in them via the
[1, 2, 3].length // 3.
length doesn't work like other keys/indexes in objects/arrays — it updates automatically, and if we change it, we change the whole array.
var myArray = [1, 2, 3] myArray.length // 3 myArray.length = 1 myArray //  (!!!)
var array = [1, 2, 3]; array.myProperty = "I'm a property!";
Which can lead to weird behavior:
array; // [1, 2, 3]; // Where did our property go? array.myProperty; // "I'm a property!"; array.length; // 3 - Would you have expected 3 or 4?
We don't tend to do these kinds of things on purpose, but it's important to be aware that they can happen so that you have a good sense of where to look if/when strange bugs start to appear.