Not So Easy Functional Programming in JavaScript
In this quick tutorial, we go over how to implement the fundamentals of functional programming in our JavaScript code.
Join the DZone community and get the full member experience.
Join For FreeIntroduction
JavaScript allows for operating on arrays in a functional way, e.g. using filter
or map
functions. As an argument for these functions, we can pass lambda expressions or function references. Is there a difference between them? The answer is yes.
What's the Problem?
In our project, we are building a mapping using the String.fromCharCode
function. To simplify the usage of this function, my code looked similar to:
[66, 67, 68].map(v => String.fromCharCode(v))
When we run this code with the node we received [ 'B', 'C', 'D' ]
, but when we decided to refactor it to use a function reference the result was different:
> [66, 67, 68].map(String.fromCharCode)
[ 'B\u0000\u0000', 'C\u0001\u0000', 'D\u0002\u0000' ]
What Happened?
To find the reason for this behavior, let's first play with the function String.fromCharCode
alone:
> String.fromCharCode(66)
'B'
> String.fromCharCode([66, 67, 68])
'\u0000'
> String.fromCharCode(66, 67, 68)
'BCD'
String.fromCharCode
deals with various types and numbers of arguments.
Now, let's examine the function map
:
> [66, 67, 68].map(v => v)
[ 66, 67, 68 ]
> [66, 67, 68].map((v, u) => [v, u])
[ [ 66, 0 ], [ 67, 1 ], [ 68, 2 ] ]
> [66, 67, 68].map((v, u, w) => [v, u, w])
[ [ 66, 0, [ 66, 67, 68 ] ],
[ 67, 1, [ 66, 67, 68 ] ],
[ 68, 2, [ 66, 67, 68 ] ] ]
map
, like many other array functions, passes always three arguments to the function. The first is thecurrent value, the second is the index of the current value, and the third is the whole array.
It means that passing String.fromCharCode
to the map
function under the hood looks like this:
> [66, 67, 68].map((v, u, w) => String.fromCharCode(v, u, w))
[ 'B\u0000\u0000', 'C\u0001\u0000', 'D\u0002\u0000' ]
And this is equal to the initial example.
Conclusion
We have to be careful when we want to use a function which can take more than one argument, but we want to pass only the value. We have to pass the function as a lambda expression:
> [66, 67, 68].map(v => String.fromCharCode(v))
[ 'B', 'C', 'D' ]
or create another function which ensures that only the first argument will be passed to the desired function:
> const useOnlyValue = f => v => f(v);
undefined
> [66, 67, 68].map(useOnlyValue(String.fromCharCode))
[ 'B', 'C', 'D' ]
Published at DZone with permission of Dominik Przybysz. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments