20
3 useful JavaScript Generic Function Currying methods
There are some cases when you deal with multiple functions either when they are completely separate or depend on each other. I'm sure you have stumbled upon the problem that could use some helpers. I will present some methods I found useful for dealing with that problem.
I'm not an expert by any means, this blog is just result of me learning and trying to understand some concepts deeper while sharing it. Maybe someone will find it interesting. Any feedback appreciated.
Let's start from something easy to read. One of the simplest yet powerful examples is runAll
function you could implement as following:
const runAll = (...fns) => fns.forEach(func => func?.())
It runs all functions one by one.
If you don't know what this (
func?.()
) does it just runs function only when it's defined
const handleRefresh = runAll(closeModal, clearSearch, clearFilter, clearSort)
handleRefresh()
It's just a simple and elegant solution when you want to run multiple void functions. I personally think that it helps to keep your code clean and DRY.
If your functions depends on each other you might want to use function chaining similarly to:
const chain = (...fns) => (...args) => fns.reduce((arg, func) => func(arg), args)
It runs functions one by one passing previous function result as the parameter.
This one-line function is incredibly powerful and gives you lots of possibilities.
If you want to have more math alike nesting you use
reduceRight
so if you combinea,b,c
it's interpreted asa(b(c))
instead ofc(b(a))
.
const increment = (x) => +x + 1
const decrement = (x) => +x - 1
const square = x => x * x
const chained = chain(increment, square, decrement)
console.log(chained(2)); // 8
Value passed as an argument is first incremented then squared and finally decremented. Kind of silly example, but you get the idea.
Sometimes you only care about combining the results of function. Usually it's only two functions but if you have to write it anyway why not make it generic?
const combine = (...fns) => (...args) => fns.reduce((results, func) => ({ ...results, ...func?.(...args) }), {})
It's little bit harder to read but all it does is running all functions with the same parameters and then combining the results.
const funcA = (prop) => ({
common: 'A',
propA: 'A ' + prop
})
const funcB = (prop) => ({
common: 'B',
propB: 'B ' + prop
})
const funcC = (prop) => ({
common: 'C',
propC: 'C ' + prop
})
const combined = combine(funcA, funcB, funcC)
console.log(combined('demo')) // { common: 'C', propA: 'A demo', propB: 'B demo', propC: 'C demo' }
As you can see unique properties of the objects are all present in the result, but the common
that was shared between all functions got overridden by funcC
.
It's the same as just calling all functions and doing
{...resA, ...resB, ...redC}
That's all I came up with when it comes to functions one-liners. Have you ever used something similar in a project?
20