The magic of Array iteration in Javascript
A cheat sheet to understanding it all
Javascript provides us with the Array composite type so we can easily create dynamically sized and loosely defined lists in our application. Understanding how to effectively iterate arrays is essential to letting us properly manage and utilise them. The question is do you know all the methods available?
We will use the following array list throughout our examples:
const eArray = ["val1", "val2", "val3", "val4"]Non-prototypal methods:
Simple for loop:
The bane of many a functional programmer, we can use the trusty for loop to iterate Arrays.
- Reassigns and increments the value of i from our initially set index (0) while its value is less than the array length. Uses i to refer to each position of the array.
- Current iteration can be skipped with continue
- Can be short circuited with break or return
for (let i = 0; i < eArray.length; i++){
if (eArray[i]==="val1") continue;
console.log(eArray[i]);
if (eArray[i]==="val3) break;
}/*
val2
val3
*/
for…in iteration:
We can also use the object iteration syntax on Arrays.
- Assigns the value of pos to the current iteration location from 0 index
- Can use const as long as no reassignment is made to pos in curly brace
- Current iteration can be skipped with continue
- Can be short circuited with break or return
for (const pos in eArray){
console.log(eArray[pos])
}/*
val1
val2
val3
val4
*/
for…of iteration:
for…of directly assigns the value of the array instead of a positional index as with for…in
- Assigns the value of item to value of current index location
- Can use const as long as no reassignment is made to item in curly brace
- Current iteration can be skipped with continue
- Can be short circuited with break or return
- Syntax directly addresses value so no access to index of iteration
for (const item of eArray){
console.log(item)
}/*
val1
val2
val3
val4
*/
Prototypal Methods
For reference we can get a list of accessible prototypes using:
console.log(Object.getPrototypeOf([]))Lets go through them according to use case:
I want to iterate everything unconditionally and perform a task on each item
- Use the forEach prototype
- We pass in a function which is executed per item. Our function does not need to return a value
- The end result of for…each returns undefined: you are interested in performing logic in your function, not a return value
- return can be used to skip iteration like continue can in standard loops
- Cannot be short circuited, must iterate to end
console.log(
eArray.forEach((item, i, array)=>{
if (item==="val2") return;
console.log(item, i, array);
})
)/*
val1 0 ["val1", "val2", "val3", "val4"]
val3 2 ["val1", "val2", "val3", "val4"]
val4 3 ["val1", "val2", "val3", "val4"]
undefined
*/
I want to see if a condition exists at least once in the array
- Use includes for primitives or some prototype for composites
- includes takes a primitive param
- For some we pass in a function which enforces our criteria and:
— Returns true if the criteria is found
— Returns false if the criteria is not found - some can be short circuited. The end result is a boolean:
— true if criteria is found. Short circuit happens on first true (ie. some elements meet our criteria)
— false if criteria is not found. This will iterate all values (ie. we are sure no values contain our criteria)
// Using some prototype
console.log(
eArray.some((item, i, array)=>{
console.log(item, i, array)
return item === "val2"
})
)/*
val1 0 ["val1", "val2", "val3", "val4"]
val2 1 ["val1", "val2", "val3", "val4"]
true
*/// Using includes
console.log(
eArray.includes("val2")
)
/*
true
*/
I want to check a condition exists in every item of the array
- Use the every prototype
- We pass in a function which enforces our criteria and:
— Returns true if the criteria is found
— Returns false if the criteria is not found - Can be short circuited and end result is a boolean:
— true if criteria is met. This will iterate all values (ie. we are sure every value meets our criteria)
— false if criteria is not found. Short circuit happens on first false (ie. we are sure not every value meets our criteria)
console.log(
eArray.every((item, i, array)=>{
console.log(item, i, array)
return item === "val1"
})
)/*
val1 0 ["val1", "val2", "val3", "val4"]
val2 1 ["val1", "val2", "val3", "val4"]
false
*/
I want to find the location of a value in the array
- If you have an array of primitives you can use indexOf otherwise use findIndex. If you’re in search of the last value of a primitive, use lastIndexOf which reverses the direction of the lookup from left to right to right to left
- Returns -1 if the value is not found, otherwise will return the location of the item as a 0 indexed integer
- Will short circuit on the first found item
// Using findIndex for non-primitives
console.log(
eArray.findIndex((item, i, array)=>{
console.log(item, i, array)
return item === "val2"
})
)/*
val1 0 ["val1", "val2", "val3", "val4"]
val2 1 ["val1", "val2", "val3", "val4"]
1
*/// Using indexOf for primitives
console.log(
["val1", "val2", "val3", "val2"].indexOf("val2")
)/*
1
*/// Using indexOf for primitives
console.log(
["val1", "val2", "val3", "val2"].lastIndexOf("val2")
)/*
3
*/
I want a transformed array to fulfill another purpose
- Use the map prototype
- We pass in a function which will take the current value and return the target structure we want to transform into
- The end result is an identically sized array consisting of the newly transformed objects
- If you need to mutate size consider using filter before/after a map transformation (depending on which is most efficient in your case)
console.log(
eArray.map((item, i, array)=>{
console.log(item, i, array)
return item === "val2" || item === "val4"
})
)/*
val1 0 ["val1", "val2", "val3", "val4"]
val2 1 ["val1", "val2", "val3", "val4"]
val3 2 ["val1", "val2", "val3", "val4"]
val4 3 ["val1", "val2", "val3", "val4"]
[false, true, false, true]
*/
I want to accumulate my array into a single value
- Use the reduce function (for left to right iteration) or reduceRight (for right to left iteration)
- We pass in a function which takes an accumulator and the current value
- All items are iterated allowing us to “accumulate” into our accumulator
- The end result is our accumulator
console.log(
eArray.reduce((accumulator, item)=>{
console.log(accumulator, item)
return accumulator += item
})
)/*
val1 val2
val1val2 val3
val1val2val3 val4val1val2val3val4
*/
