Functional programming applied to JavaScript
Understanding functional programming
Functional programming applied to JavaScript

Understanding functional programming
In this article, I will apply the functional programming paradigm to the JavaScript language. A wonderful language that can be used both on the front end and the back end. But here’s the problem: this language is accessible to any developer, both experienced and junior, and that’s precisely the issue. JavaScript is so permissive that it is very easy to make something that works — but what about the quality of the code? Is it understandable or easily maintainable for evolution or simply for correction?
- Have you ever wondered what the major cause of bugs in a computer program could be?
- How could we simplify the reading of code and thus its understanding by another developer?
- What does functional programming bring to a language like JavaScript?
The answer to the question “what could be the major cause of bugs in a program?” is simple, and one of the major causes is:
=> Poor variable management
Well then! Let’s remove the variables!
Imagine a program where there are no more variables!
If there are no more variables, then the code becomes predictable. And if the code becomes predictable, then we can guarantee the behavior and confidently say, “Yes, my code is robust and bug-free.”
Indeed, imagine a function whose behavior you can guarantee and confidently assert that it has no bugs, that would be fantastic! Well, it exists and it is called a pure function!
Ensuring the behavior of a function
Pure functions
- A pure function is a function that does only what it is intended to do and nothing else. A single responsibility!
- A pure function is a function without side effects, meaning it does not modify any global variables!
- A pure function is a function that uses only the parameters passed in arguments, no environment variables or global variables!
- A pure function is a function that, given the same input parameters, will always return the same output result.

Side effects
A function with side effects is a function that modifies one (or more) global variable(s). And it’s dangerous because if you use “impure” functions, there is a risk that it will not have the expected behavior when you try to execute it.
Here is a concrete example of an “impure” function coupled with a function that causes unexpected behavior, thus having a side effect on the program:
var a = 2;
const add = (var1) => var1 + a;
const doCoffee = (preparationDuration) => {
a = preparationDuration;
}
add(5); // returns 7
doCoffee(10);
add(5); // returns 15
You see that by executing the “add” function twice, we get “7” the first time and “15” the second time. Therefore, we cannot predict the behavior of the “add” function because it is not pure and the “doCoffee” function has a side effect!
Now, it is very easy to correct the “add” function to make it “pure”
var a = 2;
const add = (a, b) => a + b;
const doCoffee = (preparationDuration) => {
a = preparationDuration;
}
add(5, 3); // returns 8
doCoffee(10);
add(5, 3); // returns 8
Here, the “add” function uses only the parameters passed as input and the “doCoffee” function, which has a side effect, no longer has any impact on the “add” function, which is now pure. You can execute the “add” function as many times as you want! And if you pass the same parameters each time, it will always return the same result!
Composition
Now that you have pure functions, you just need to combine these functions to build a complete program or at least a more advanced functionality than a simple addition. Composition is the chaining of several pure functions.
const multiply = (a, b) => a * b
const divide = (a, b) => a / b
const add = (a, b) => a + b;
const result1 = add(5, 3); // returns 8
const result2 = multiply(result1, 3); // returns 24
const result3 = divide(result2, 6); // returns 4
We can also write this program by removing the intermediate variables.
const result3 = divide(multiply(add(5, 3), 3), 6); // returns 4
Admit that this is not much better in terms of readability or code maintenance…
Imagine if we could create a function that would handle chaining the three functions — we would pass it an input value, it would handle the processing internally by performing the necessary operations, and it would always return the same result with the same input value.
Example in image

To arrive at this solution, we still have some work to do.
Indeed, what means do we have to pass a value through several functions? Well, the first function must take only one parameter as input, process that data, and then pass it to the second function. This second function then takes as input the result of the first function. Be careful, this second function is therefore limited to a single input value — it then performs its processing and then returns the result to the third function. In turn, the third function takes as input the result of the second function — performs its processing and finally returns the final result!
Well, the function that allows such a process is commonly called the “compose” or “pipe” function. It is provided with any library that allows functional programming like Ramda or Remeda. If you do not want to bother with an external library, know that it is possible to create your own “pipe” function quite easily. We will see it later at the end of this article.
Now, we will need to modify our “add”, “multiply”, and “divide” functions a bit to make them unary functions, i.e., functions with an arity of 1.
In mathematics, the arity of a function represents the number of arguments it accepts.
In other words, we need to transform our functions so that they only accept a single argument. This notion is called “currying.”
Currying
Currying is transforming a function that accepts “n” arguments into a series of functions that only accept one argument at a time.
Example of an initial function accepting two arguments:

Example with the same “add” function but in curried version:

In other words, the curried version will return a new function each time until all the necessary parameters for the final operation are present.
Let’s see a more concrete case:
const add = (a) => (b) => a + b
const add3 = add(3)
const result = add3(5); // returns 8
Conclusion: composing pure functions
Transforming the binary function (with an arity of 2) into a unary function (with an arity of 1) that only accepts one argument at a time makes this function composable, and that’s where the magic starts to happen!
Now let’s add the “multiply” and “divide” functions.
const add = (a) => (b) => a + b
const multiply = (a) => (b) => a * b
const divide = (a) => (b) => b / a
const add3 = add(3)
const multiplyBy3 = multiply(3)
const divideBy6 = divide(6)
Now that these functions are composable, we can perform composition and create the following function:
const calculate = pipe(
add3,
multiplyBy3,
divideBy6,
)
const result = calculate(5); // returns 4
Remember the syntax used at the beginning of the article:
const result3 = divide(multiply(add(5, 3), 3), 6); // returns 4
Without the “pipe” function, the calculate function would be written as follows:
const calculate = (a) => divideBy6(multiplyBy3(add3(a)))
const result = calculate(5); // returns 4
But admit that the reading is much simpler with the “pipe” syntax, which offers a linear reading of the code 🙂
Your code is now more readable and more easily maintainable and scalable. And more importantly, you are now able to guarantee the behavior of your program. You can execute your “calculate” function as many times as you want — if you pass the same parameter as input, your function will always return the same result, regardless of the execution context of your function. Your function is portable, you can reuse it in any other program without risking altering its behavior because your function is a composition of pure functions. No other function with side effects will be able to alter the behavior of your function. And that is priceless!
And as promised, if you don’t want to bother with external libraries, here is the ‘pipe’ function:
const pipe = (...fns) => (data) => fns.reduce((acc, fn) => fn(acc), data);
Gael Cadoret
Senior Backend Developer & FP Evangelist
INGIN — Going Further with Functional Programming in JavaScript.
메타데이터
- post_id
- 210eb18efcfd
- slug
- functional-programming-applied-to-javascript-210eb18efcfd
- url
- https://medium.com/@gaelcadoret21/functional-programming-applied-to-javascript-210eb18efcfd
- canonical_url
- https://medium.com/@gaelcadoret21/functional-programming-applied-to-javascript-210eb18efcfd
- author_url
- https://medium.com/@gaelcadoret21
- status
- ok
- fetched_at
- 2026-09-20 21:51:47