DEV Community

Rhymes Toasterface
Rhymes Toasterface

Posted on • Originally published at Medium on

Adventures in Javascript pt.2

Well, as last week’s article was such a success (thanks for all the likes and retweets, by the way), I thought I should continue where it left off!

So, last time, we talked about map, filter and reduce, how they work and what they look like behind the scenes.

This time, we will talk about composing those functions, or chaining them together.

Again, we will look at how this looks done with our hand-made functions to get a feel for it, then do it with the “real JS functions.

Short and sweet. Nice. Let’s crack on.

We had an array:

let nums = [1,2,3,4,5,6,7,8,9];
Enter fullscreen mode Exit fullscreen mode

Using our last functions, we will map over it, adding one to each, filter it down to numbers over 5, then reduce what is left down to a total of these values. Expecting a total of 40. I think… (quick maths, u know).

Man’s not hot

Here goes:

let ourMapResults = map(nums, addOne);
// [2, 3, 4, 5, 6, 7, 8, 9, 10]

let ourFilterResults = filter(ourMapResults, moreThanFive);
// [6, 7, 8, 9, 10]

let ourReduceResults = reduce(0, ourFilterResults);
// 40
Enter fullscreen mode Exit fullscreen mode

Hurrah, and indeed, HUZZAH.

So, so happy

And, as expected, this works fine. It’s fairly simple.

“So, what’s the beef ? you may find yourself asking (you do, right?).

Firstly, you are creating all of these new variables just for the sake of being able to pass them to the next function in the chain. They won’t be used again, they won’t fulfil their life goal as variables. Or something. You wouldn’t want that for your variables, would you?

Also, each item in the chain is doing just one thing. It is easy to keep track of what is going on.

Also, this is a VERY simple example. These chains can go on for a very long time and can get vey complicated. You would have extra variables everywhere, your code base would be (probably) a lot bigger, less maintainable and a lot less clear.

There are probably lots more reasons it is better, but look - it’s a Sunday morning. Stop picking on me!

Anyway - now, let’s do than the “real” way:

let reduceResults = nums.map(addOne)
  .filter(n => n > 5)
  .reduce((sum, num) => sum + num, 0)
// 40
Enter fullscreen mode Exit fullscreen mode

Great success

Something to watch out for in this:

let reduceResults = nums.map(addOne)
  .filter(n => n > 5)
  .reduce((sum, num) => sum + num, 0)
Enter fullscreen mode Exit fullscreen mode

is the values being used. Firstly, this looks quite strange:

let reduceResults = nums.map(addOne)
Enter fullscreen mode Exit fullscreen mode

addOne doesn’t have anything passed in to it. Really, this is just:

let reduceResults = nums.map(eachNumber => addOne(eachNumber))
Enter fullscreen mode Exit fullscreen mode

map walks through the array and passes each value to the function given (remember, it is just a for loop).

Each function after it is taking the result of the previous one in the chain and bringing it in:

// n = nums.map(addOne)

.filter(n => n > 5)

/*
* It is worth noting here that the name of n can be anything. It is
* generally shortened as much as possible, but this is where it is
* made, you can call it what you want!
*/

.filter(numberOfMagicBeans => numberOfMagicBeans > 5)
Enter fullscreen mode Exit fullscreen mode

Just as an aside, some of you may be familiar with PHP and its dot concatenation (I’m thinking of you here, Bert):

“this .  is , “a . “string”
Enter fullscreen mode Exit fullscreen mode

It may help to think of chaining functions to work in a similar way:

"nums.map(addOne)" . "filter(n => n > 5)" . "reduce((sum, num) => sum + num, 0)"
Enter fullscreen mode Exit fullscreen mode

All you are really doing with the dot is accessing the methods stored on the JS array prototype object, over and over again. Remember:

nums.map(addOne) 
// nums is an array (array.prototype.map)

thatNewArray.filter(n => n > 5) 
// (array.prototype.filter)

newerArray.reduce((sum, num) => sum + num, 0) 
// (array.prototype.reduce)
Enter fullscreen mode Exit fullscreen mode

Also, don’t let the ES6 arrow functions confuse you.

They make chains like this easier to read, but watch out for the way they bind to this if you have any OO-ish code.

Really, all we are saying is,

nums.filter(function (number) { 
    return number > 5;
}
Enter fullscreen mode Exit fullscreen mode

The filter might look a bit tricksy because of all the equals signs and angle brackets (especially if we were checking for >= instead of just >)!

So, there we go. Nice, pretty composed functions.

As before, you can try this in your own terminal – copy and paste, it should work the same way.

If you have any questions, drop me a line.

Maybe there will be more (if I can think of a topic…).

Discussion (0)