Arrays and Functional Programming
We've seen Arrays since our first day of complex data types, and we've been using them in a number of different forms since then. We know that they associate data with indices, and we know that Arrays have a length
property that comes in handy during loops. What other tricks do Arrays have in store for us?
Array.prototype.*
methods
Array.prototype.*
methodsArrays have associated with them some properties, like .length
, and methods, like .push()
, to help us use our collections of data more effectively.
const arr = ["stuff", "more stuff", "even more stuff"];
arr.length;
arr.push("More on the end!!!");
const lastItem = words.pop();
arr.unshift("More at the beginning!!");
const firstItem = words.shift();
.forEach()
.forEach()
Up to this point, we've been using while
loops to iterate over Arrays. But often it's cleaner to use Array's native .forEach()
method to run a given function once for each item in the Array, passing that item in as an argument.
function logMe(word) {
console.log(`logging ${word}`);
}
words.forEach(logMe);
Portfolio Project 2
Replacing while
while
Let's turn the
while
loop in ourNavigation
component'sbuildLinks
function into a.forEach
loop instead! HINT:function buildLinks(linkArray) { let i = 0; let links = ""; let route = ""; // changed for clarity linkArray.forEach(link => { if (link !== "Home") { route = lowerCase(link); } links += ` <li> <a href='/${route}' data-navigo> ${link} </a> </li> `; }); return links; }
See if you can replace some of the other
while
loops you've created in the past with.forEach
!
Functional Programming
Since JavaScript treats functions as first-class citizens, it can be treated as more than just an imperative or Object Oriented language. Instead, we can program in a functional paradigm, where all operations are functions that focus on returned values instead of side effects. There are libraries like Underscore, lodash, and Ramda that help expand JavaScript's built-in functional tools, but there are a few that ship with JS that we should know!
.map()
.map()
Remember how while
loops are avoided because of a floating count variable? e.g.
let i = 0; // awkward counter
const limit = 10; // or some other number
while (i < limit) {
// do something
i++; // increments i outside of scope of while loop.
}
This is no good in large applications because that i
variable could easily get away from us. It's a changing and mutable
value that can't always be depended on (i.e. order matters, which is generally not good). One solution was the forEach
loop, which kept everything nice and tidy!
But .forEach
doesn't actually solve all of while
's problems. Think about how many times we've done something like this:
const myArray = [1, 2, 3, 4, 5];
const doubledNumbers = [];
myArray.forEach(function(num) {
doubledNumbers.push(num * 2);
});
See how doubledNumbers
is separated from the loop that populates it? It's the same order-specific implementation that we generally ought to avoid. What if, instead, we had a function that could create doubledNumbers
directly? Well, we do! And that function is .map()
, which is built into the Array
data type. Try this:
const myArray = [1, 2, 3, 4, 5];
const doubledNumbers = myArray.map(num => num * 2);
console.log(doubledNumbers);
Now there's no doubt that doubledNumbers
comes from myArray
, and there's no issue of order. The only state to keep track of is that of myArray
, and that value should never change if we're programming functionally!
.filter()
.filter()
How about this scenario:
const myArray = [1, 2, 3, 4, 5];
const oddNumbers = [];
myArray.forEach(num => {
if (num % 2 !== 0) {
oddNumbers.push(num);
}
});
We can filter values in the same way using the .filter()
method! .filter()
expects a return
value that filters out some results.
const myArray = [1, 2, 3, 4, 5];
const oddNumbers = myArray.filter(num => num % 2 !== 0);
.reduce()
.reduce()
Of the three functions we're learning today, reduce
is the most complex, but it's so useful that it's important to learn it! Let's think about this situation:
const myArray = [1, 2, 3, 4, 5];
let myArraySum = 0; // variable that keeps a sum of all values in myArray
myArray.forEach(num => {
myArraySum += num;
});
Now let's try to .reduce()
this array from left to right in a similar way. .reduce()
takes four possible arguments, but we're going to use the first two (the running total, and the next value to add to that running total... see the docs for more information).
const myArray = [1, 2, 3, 4, 5];
const myArraySum = myArray.reduce((total, currentValue) => {
return total + currentValue;
});
More Exercises:
Write a function that takes an array of values and returns an boolean representing if the word "hello" exists in the array.
Write a function that takes an array of values and a target value and returns how many times that target value exists in the array.
Write a function that takes an array and returns a new array containing only the values at odd indexes in that array.
Write a function called sumArray that takes an array of numbers and returns the sum of all of those numbers added together.
Last updated
Was this helpful?