Arrays
Arrays are a fundamental datatype in JavaScript. Like arrays in other languages, they represent an ordered collection of values, where each element has a numeric position in the array. Numbering begins at zero. Unlike other languages, JavaScript arrays are not typed; elements of the same array may be of different types. JavaScript arrays are also dynamic - the size can grow and shrink during execution so there is no need to declare a size up front.
- JavaScript arrays can hold values of different types.
- The size of an array is dynamic. It can grow and shrink during program execution.
- No need to specify the array size up front.
- Arrays can be constructed with either the new keyword with the Array() constructor, or with array literal notation -
[ ]- - square brackets - length returns the size of the array
creating arrays
You can create an empty array in several different ways:
let scores = new Array();
let artists = Array();
let emptyArray = [];
If you know the number of elements, you can create an array of a particular size:
let scores = Array(10);
You can create and initialize an array with values:
let scores = new Array(9,10,8,7,6);
let colors = ['red', 'green', 'blue'];
length
length returns the size of the array:
console.log(colors.length);
outputs this to the console:
push and pop
To add elements dynamically to the end of an array use push:
myarray.push('new item');
Then, you can remove an item from the end of an array with pop:
lastitem = myarray.pop();
In the example below, we create an array, teams, with three elements. We add a new team with push and then remove the last element added with pop:
let teams = ['Falcons', 'Saints', 'Panthers'];
teams.push('Jaguars'); // added to end
console.log(teams);
const lastElement = teams.pop(); // pop last element
console.log(lastElement);
and this is the output:
indexOf and isArray
You can find the index of an array element with the indexOf() method. Determine if a value is an array with the isArray() method:
let index = teams.indexOf('Panthers');
console.log(index);
console.log(Array.isArray(teams));
Destructuring
Array destructuring provides a convenient way to extract elements from an array or properties from objects in a single line of code.
Destructuring provides short, clean syntax to unpack to distinct variables:
- values from an array
- properties from objects
With this array:
const league = ["Steelers", "Falcons", "Patriots", "Browns"];
we can extract teams from the array with:
let team1 = league[0];
let team2 = league[1];
but a cleaner approach is to use destructuring:
let [team1, team2] = league;
Spread
The JavaScript spread operator (...) provides a concise way to expand an array into its individual elements. This functionality is useful in several situations:
- copying arrays
- merging arrays
- adding elements to an array
- passing elements of an array as arguments
copying
The spread operator is a convenient way to create a copy of an array.
let a = [1,2,3];
let copy = [...a];
console.log(copy);
yields the following to the console:
If I change an element of the copy, does that affect the original?
copy[0] = 0;
console.log(a[0]);
console.log(copy[0])
yields the following to the console:
merging
Use the spread operator to combine multiple arrays into a new array.
const numbersOne = [1, 2, 3];
const numbersTwo = [4, 5, 6];
const numbersCombined = [...numbersOne, ...numbersTwo];
console.log(numbersCombined);
yields this output:
adding elements
New elements can be easily added to an array, either at the beginning, end, or in the middle, by spreading an existing array and including the new elements.
let a = [1, 2, 3];
let b = [0, ...a, 4];
console.log(b);
yields the following output:
The three dots "spread" the array a so that its elements become elements within the array literal being created. Essentially, the ...a is replaced by the elements of a.
passing array elements
When a function expects individual arguments, the spread operator can be used to expand an array into those arguments.
function sum(a, b, c) {
return a + b + c;
}
const values = [1, 2, 3];
console.log(sum(...values));
yields the following output:
for/of
The easiest way to loop through each element of an array is with the for/of loop. for/of:
- runs once for each element
- works with iterable objects:
- arrays,
- strings,
- sets, and
- maps
Set it up using the keywords as in this sample code:
for ( variable of iterable_object) {
body
}
The following two loops are functionally equivalent:
years = [1952, 1999, 2001, 2011, 2020, 2025];
for (let i = 0; i < years.length; i++) {
let yr = years[i];
console.log(yr);
}
for (let yr of years) {
console.log(yr);
}
Both implementations yield:
Strings are iterable objects so can be iterated with:
const iterable = "boo";
for (const value of iterable) {
console.log(value);
}
Results in the following output:
Array methods
forEach
ForEach iterates through an array invoking a function you specify for each element. You pass the function as the first argument and forEach() then invokes your function with (optionally) three arguments:
- the value of the array element,
- the index of the array element
- the array itself If you only care about the value of the array element, you can write a function with only one parameter - the additional arguments will be ignored. For example, we can sum the elements:
let data = [1,2,3,4,5];
let sum = 0;
data.forEach(value => sum += value);
console.log(`result of forEach: ${sum}`);
which outputs:
We can increment each array element, :
data.forEach((v, i, a) => a[i] = v + 1);
console.log(`incremented array: ${data}`);
which yields:
To execute a function on each element:
numbers = [1,2,3,4,5];
function print(element) {
console.log(element)
}
numbers.forEach(print);
map
map() passes each element of the array on which it is invoked to the function you specify and returns a new array of the same size containing the values returned by your function.
The function you pass to map() is invoked in the same way as a function passed to forEach(). For the map() method, however, the function you pass should return a value; that value becomes the entry in the new array.
map returns a new array. The array map is invoked on is not modified.
Consider this example:
const numbers = [1,2,3,4,5];
const newNumbers = numbers.map(function (num) {
return num * 2;
})
console.log(newNumbers);
or use an arrow function. Which is more readable?
const newNumbers = numbers.map ( num => num * 2 );
console.log(newNumbers);
Both output:
Consider this list of movies in watchList:
watchList = [
{
"Title": "Inception",
"Year": "2010",
"Rated": "PG-13",
"Released": "16 Jul 2010"
},
{
"Title": "Interstellar",
"Year": "2014",
"Rated": "PG-13",
"Released": "07 Nov 2014",
},
{
"Title": "The Matrix",
"Year": "1999",
"Rated": "R",
"Released": "31 March 1999",
}];
To create a ratings array that includes just the Title and Rated property of each movie we could use push on each element:
let ratings = [];
for(let i=0; i < watchList.length; i++){
ratings.push({title: watchList[i].Title,
rating: watchList[i].Rated});
}
console.log(ratings);
or we could accomplish this with map:
const ratings = watchList.map(movie => ({
title: movie.Title,
rating: movie.Rated
}))
console.log(ratings);
Both versions yield:
[
{ title: 'Inception', rating: 'PG-13' },
{ title: 'Interstellar', rating: 'PG-13' },
{ title: 'The Matrix', rating: 'R' }
]
filter
Filter: creates a new array with all elements that pass the test implemented by the provided function. filter() returns a subset of the elements of the array.
The function passed should return true or false.
For example, to keep the numbers less than 3 in a new array:
const numbers = [1,2,3,4,5];
let underThree = numbers.filter(function (num) {
return num < 3;
})
console.log(`filtered: ${underThree}`);
The above filter on numbers yields:
Or to keep even numbers in the new array:
let evenNumbers = numbers.filter(n => n%2 === 0)
console.log(`filtered: ${evenNumbers}`)
The above filter results result in the following console output:
filter returns a new array. The array filter is invoked on is not modified.
find / findIndex
find() and findIndex() iterate through the array looking for elements where the passed function returns true. Similar to filter, you are to pass a boolean function; unlike filter, find() stops iterating the first time a matching element is found. findIndex() returns the index and find() returns the matching element. If no matching element is found, find() returns undefined and findIndex() returns -1.
Consider these examples:
const numbers = [1,2,3,4,5];
let mult_5 = numbers.find(x => x%5 === 0)
let mult_7 = numbers.find(x => x%7 === 0)
let ind_3 = numbers.findIndex(x => x === 3)
console.log(mult_5);
console.log(mult_7);
console.log(ind_3);
yields the following output:
sort / toSorted
sort orders the elements of the array in place and returns the sorted array. When called with no parameters, sort() sorts the elements in alphabetical order.
To sort an array into some order other than alphabetical, a comparator function must be provided. The function determines the order of the elements. It takes two arguments, often referred to as a and b, and returns:
- A negative value if a should come before b
- Zero if a and b are considered equal (keeps original order)
- A positive value if a should come after b
sort modifies the original array
const fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
console.log(fruits);
const a = [33, 4, 1111, 222];
a.sort(); // alphabetical order
console.log(a);
a.sort((a,b)=> a-b); // ascending order
console.log(a);
a.sort((a,b)=> b-a); // descending order
console.log(a);
Yields output as follows:
The toSorted() method is available in newer JavaScript. toSorted creates a new array with the sorted
elements, leaving the original array in tact. Here's an example:
const numbers = [10, 2, 5];
const sortedNumbers = numbers.toSorted((a, b) => a - b);
console.log(numbers);
console.log(sortedNumbers);
reduce
Reduce combines the elements of an array, using the function you pass as a parameter, to produce a single value. reduce() takes two arguments: the function that performs the reduction operation and the second (optional) argument is an initial value to pass to the function.
The task of the function is to combine or reduce two values to a single value and return the reduced value.
const numbers = [1,2,3,4,5];
let ss = numbers.reduce((x,y) => x+y, 0)
let prod = numbers.reduce((x,y) => x*y, 1)
console.log(ss);
console.log(prod);
yields the following output:
every and some
every() and some() apply a predicate function you specify to the elements of the array, then return true or false.
const numbers = [1,2,3,4,5];
let e = numbers.every(x=> x < 10)
let s = numbers.some(x => x%2 === 0)
console.log(e);
console.log(s);
As seen below, both every and some return true because all numbers are less than 10 so every results in true. Also at least one number in the numbers array is even so some returns true as well. Output of every and some in above example: