Modify Functions with Higher Order Functions in JavaScript

Kyle Shevlin
InstructorKyle Shevlin

Share this video with your friends

Send Tweet
Published 4 years ago
Updated 3 years ago

This lesson teaches the concept of higher order functions (HOF) in JavaScript, a necessary building block of functional programming in any language.

A higher order function does at least one of the following things, often both:

  1. Accepts a function as an argument
  2. Returns a new function

To demonstrate this, we will build a higher order function, withCount(), that modifies any function passed to it so that it logs out how many times it has been called.

Instructor: [00:00] A higher order function is any function that does at least one of the following two things, and oftentimes does both. First, it accepts a function as an argument. Second, it might return a new function.

[00:15] To demonstrate this, we're going to create a width, count higher-order function. With count, we'll take a function as an argument. What it will do is return a console log of how many times we've called our newly return function from within it.

[00:31] To do this, we'll store a count variable. We'll return a new function that uses the rest operator to gather up the arguments passed to it. Inside the body of our return function, we'll log out the count while also incrementing it. We'll return the results of the function that's been called with the spread arguments.

[00:52] Now that we have our width, count higher-order function, let's create a simple add function to use and pass into it. It will receive X and Y as arguments and return their summation. We can now create a counted add function by using our width, count function and passing add to it.

[01:10] Now, let's log out several uses of counted add. I'll modify some of the arguments. If we save this and print it out in the terminal, we should see a call count with each one.

ludwig
ludwig
~ 3 years ago
console.log(countedAdd(1, 2));
// Call count : 1
console.log(countedAdd(2, 2));
// Call count : 2
console.log(countedAdd(3, 2));
// Call count : 3

it's can be interested to talk about clojure here

Henri d'Orgeval
Henri d'Orgeval
~ 3 years ago

It would have been even greater if you had explained how to retrieve the count value within the higher order function. I was expected something like that: countedAdd.count

Kyle Shevlin
Kyle Shevlininstructor
~ 3 years ago

@hdorgeval this is a lesson on higher order functions, not on closures. A lesson on closures could show you how to expose the count value.

Also what you're asking is to add a property to the incoming function, which is possible, but could potentially be unsafe. Adding properties to functions and objects could overwrite functionality already stored at that property key. It is possible that the passed in function has a count property already, and thus if we added it, we'd be breaking the API of the function.

Karol Mazur
Karol Mazur
~ 3 years ago

@Kyle I'm confused by this lesson. To me intuitively functions are stateless: you put a value in, you get a value out. Using withCount you've hidden state inside of a function. So now calling that function multiple times (even with the same input) causes a side effect. I think I get it... it's just not intuitive at all. Any help appreciated.

Kyle Shevlin
Kyle Shevlininstructor
~ 3 years ago

Hi Karol,

Your intuition is only accurate if the function doesn't create a closure. Our higher order component, while a pure function (because it always returns the same function when given the same inputs), creates a closure that holds the count in state, Every time you use withCount to modify a function, you create a new closure holding a new count in that state. Then when you call the modified function, the side effect reads and updates that state held in closure.

This isn't a lesson on closures, but understanding them would help you understand how this higher order function works.

Hope that helps!

Karol Mazur
Karol Mazur
~ 3 years ago

@Kyle thanks for the quick response! I understand closures, but what's throwing me off here is that a function is keeping a reference to a closure. Hmm, I think coming from an Objective-C and Swift background I'm still very affected by thinking in an OO-way.

Kyle Shevlin
Kyle Shevlininstructor
~ 3 years ago

At least in JavaScript, this is exactly the point of the closure, to hold some bit of state in memory that's still accessible by the exposed function or object. I have never written any Objective-C or Swift, so I can't really speak to the similarities or differences.

Karol Mazur
Karol Mazur
~ 3 years ago

Thank you @Kyle. :)