JavaScript is partly a functional language.
To learn JavaScript, we got to learn the functional parts of JavaScript.
In this article, we’ll look at how to use closures to create our own higher-order functions.
unary Function
We can create our own unary
function that returns a function that only calls one argument.
For example, we can write:
const unary = (fn) =>
fn.length === 1 ?
fn :
(arg) => fn(arg)
We have the fn
which is a function.
We check the length
property of fn
, which returns how many parameters it has.
If it only has one parameter, then we return the fn
function.
Otherwise, we return a function that calls fn
with only one argument.
This way, we can use functions like parseInt
with the map
method safely.
For example, we can write:
const nums = ['1', '2', '3'].map(unary(parseInt));
We call the unary
function with parseInt
so that we can use the callback withn only of parameter to parse the string to an integer.
parseInt
takes the value to parse, and the radix as the second argument, so we can’t just pass parseInt
straight to map because the radix will be the index of the array entry, which isn’t what we want.
With our unary
function, we always call parseInt
with only the value passed in.
Therefore, nums
is [1, 2, 3]
.
once Function
We can create a once
function to only call a function once.
For example, we can write:
const once = (fn) => {
let done = false;
return function(...args) {
if (!done) {
done = true;
fn.apply(this, args);
}
}
}
We have the once
function, which only runs the fn
function that’s passed in when done
is false
.
If that’s the case, then we set done
to true
and call fn
with apply
.
apply
takes the this
value as the first argument and the array of arguments as the 2nd argument.
Then we can use it to only call a function once by writing:
const foo = once(() => {
console.log("foo")
})
foo();
foo();
We call the once
function with a function that we only want to call only once.
Then we can call it twice and see that 'foo'
is only logged once.
Memoize
We can cache the return value of our function call by creating our own memoize
function.
For example, we can write:
const memoize = (fn) => {
const cache = {};
return (arg) => {
if (!cache[arg]) {
cache[arg] = fn(arg);
}
return cache[arg]
}
}
We created a memoize
function that takes the fn
function.
In the function, we define the cache
object.
And we return a function that takes the arg
argument.
We check if cache[arg]
is in the cache.
If it’s not, then we set the value in the cache
object.
And then we return the cached value.
Then we can use it by writing:
let fastFib = memoize((n) => {
if (n === 0 || n === 1) {
return 1;
}
return n + fastFib(n - 1);
});
We pass in our Fibonacci function to return the Fibonacci number given the value of n
.
This is much faster since we can look up the past computed values from the cache
object.
Conclusion
We can create our own higher-order functions to do various things with it.