Functional JS: First Class Functions
This is the first in a series of posts I plan to write about Functional Programming in JavaScript. I'm going to do my best to keep each of these small and focused, just like your functions should be. 😉
I figured we'd start this series with a fundamental feature of JavaScript that makes using it for functional programming possible. Functions in JavaScript are first class. This allows us to do some very important things with functions:
Functions can be stored in a variable or constant
Just as I can store a number or a string in a variable, I can store a reference to a function in a variable. This allows us to write function expressions and store references to existing functions in new variables if we want to.
const add = function (a, b) {
return a + b
}
let doAddition = add
add(1, 2) // 3
doAddition(1, 2) //3
Functions can be passed into other functions as arguments
It stands to reason that if you can store a function reference in a variable, then that would include parameters for other functions. If you've written any JavaScript, you've most likely seen this in action. Anytime you use a callback, you're passing a function to another function as an argument. This is common when using functions such as map
:
const numbers = [1, 2, 3, 4, 5]
const double = function (num) {
return num * 2
}
// Using `double` with map
numbers.map(double)
// Or using an anonymous version of the double function
numbers.map(function (num) {
return num * 2
})
// Or, using an arrow function
numbers.map((num) => num * 2)
Functions can be the return value of other functions
Functions can take functions in, but they can also return them.
Let's say I needed to be able to create multiple functions that increment a number by a specific amount. So I want a function that always adds 2 to a number, and another one that always adds 5. I can create a function that takes the first number (the 2 or the 5) and returns a new function. When called with the second value, the function will finish the calculation and return the resulting value.
const addN = function (num1) {
return function (num2) {
return num1 + num2
}
}
const addTwo = addN(2) // returns a function
const addFive = addN(5) // returns a function
addTwo(1) // 3
addFive(1) // 6
addTwo(2) // 4
addFive(2) // 7
A quick word about closures
Now, you might be asking how addTwo
knows that num1
is 2
and addFive
knows that it's 5
. This works because the function that is returned from addN
is a closure. This means you get back the function along with its surrounding environment and that includes the num1
argument as it exists in the environment for that instance of the function.
Higher order functions
If a function takes a function as an argument, returns a function as its result or both, it's called a higher order function.
From the examples above, both the map
method and our addN
function are higher order functions.
This is just scratching the surface, but understanding and thinking about functions as first class citizens in JavaScript will be crucial to pursuing writing JavaScript in a functional style. If any of these samples seemed a bit strange, that's okay. Eventually, this will all start to feel perfectly normal.