Functional Programming In JavaScript for Beginners
This is the first of a five-part series
What is Functional Programming?
Functional programming is a style of creating programs that:
Encourages the use of functions that are self-dependent and do not modify or depend on external values outside of their scope. This is the term pure functions.
Revolves around the concept of immutable data. This means that once data is created it cannot be modified but rather, new data is formed from existing data.
Treats functions as first-class citizens. In this style of writing code, functions are seen like any other variable in other programming languages. This gives them special powers to be passed as arguments, returned as results, and stored as values in memory.
Okay I know that was a lot so let me break it down for you in this way. Think of the game lego and how it involves small pieces of pre-built blocks that can be combined in different ways to create a visual of something whole like a car. Each lego block is independent of other lego pieces and if we wanted to modify parts of the car we were creating, we'd only need to remove the pieces that do not conform to the new visual instead of tearing down the whole thing and starting over.
This is the basic idea behind Functional programming and the lego blocks represent our functions that should be built to work on a specific type of data without causing side effects outside of their own scope (pure function). Assuming we remove one function, our application should not break just the same way if we remove one lego block we shouldn't have the whole car collapse. It's worth noting though that all functions cannot be pure functions but the aim is to encourage the use of this paradigm where possible as much as you can.
Why Functional Programming?
Traditional programming languages like C and Java take a more imperative approach where a programmer must describe every step that the program should take and tell it how to do it. Whereas Functional Programming, specifically JavaScript, relies on these new powers that functions have to offer an approach that is more declarative.
Here, we only need to define what we want to happen without worrying about how the program will do it. You may wonder how is that possible. To just say what you want and have it happen? "Yeah, I'm telling you FP has powers so stay with me here and I'll show you how."
The techniques used in functional programming such as: combining multiple functions together (composability), the immutable way of creating data, and lastly, High-order functions which are functions that take and return other functions, are what enable us to declare what we want and the underlying language takes care of how the program will perform these steps.
Let's look at the code samples below to understand these statements better.
Imperative VS Declarative Approach
Imperative approach in JavaScript
If you observe the imperative approach, you realize it needs to be handled with a lot of care and precision due to several reasons:
In the "for loop", the program must be instructed on how to iterate step by step (imperative) which may cause readability concerns and is more prone to errors if the loop is not correctly written.
The handling of the sum variable is also prone to errors since we manually manage how it's updated at each iteration. The loop is changing the state of values outside it and if at any point in it's execution another part of the program updates the sum variable, the output would be wrong.
Declarative approach in JavaScript
In the declarative approach, we call upon the mighty high-order functions which as discussed earlier, are functions that receive other functions as an argument. The array method "reduce" is used to perform the same task as the previous example but in a functional programming style.
The reduce method from the example takes a callback function and an initial value of "0", and iterates over the whole array executing the logic in the Callback for each item in the array. At each iteration, a new sum is created and passed as the "accumulator" parameter.
With this approach the code is much simpler to write and reason about because of the following reasons:
Since reduce is an array method, JavaScript already knows to take care of the iteration process we do not need step-by-step instructions on how to loop which can save time and avoid small errors (declarative).
The logic in the callback function is executed for each number in the array and at each iteration, a new accumulator value is generated as the sum of the previous iteration. This approach is wonderful since we are not manually updating the accumulator (immutability). Therefore as long as we don't interfere inside that logic, the accumulator is not susceptible to unwanted modifications. As long as the same values are passed the reduce method will always give the correct output.
Key Takeaways:
With proper observation, we start to notice that:
Functional programming encourages the use of more abstracted code that lets the methods take care of the underlying details which highly improves readability, avoids repetition and is less error-prone.
It avoids causing side effects to other parts of the program by encouraging the use of self-dependent logic.
Immutable data is very crucial to help predict the outcome of the program and keep data concurrent across the whole program.
Conclusion
I think you can start to see that functional programming creates programs that are easier to debug, test and maintain. This was just a small introduction and we'll get into the nitty-gritty of how to implement these functions in the next chapter.
That's all folks!
Subscribe to my newsletter
Read articles from CS Tora directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
CS Tora
CS Tora
MEAN/MERN Stack Engineer