Functional Programming in JavaScript – A Brain Friendly Intro

Functional programming has gained a lot of traction in the JavaScript community in the recent years. Why? This is just my personal opinion, but I believe functional programming has become a hot topic for the following reasons.

  • Because code bases are becoming bigger and bigger, stronger emphasis is being placed on writing testable code with predictable outcomes.
  • Lesser likelihood of side-effects enables us to take advantage of multi-core processors.

Therefore, I believe that every serious JavaScript developers need to get this way of thinking under their belt.

As with my other post on Big O Notation and time complexity, I will try and break down the basics of functional programming. I will continue to update this post based off feedback and suggestions, in order to make this as valuable as possible to readers. Therefore, feedback is very much appreciated!

For those that have never dabbled in functional programming, this topic can initially be very hard to understand.

Supposedly, this topic has a steep learning curve.

Therefore, I am going to attempt to explain the concepts of functional programming in the simplest way possible.

Please provide feedback on parts that are difficult to digest. That way, I can update the content so that you, as the reader, get the most out of this tutorial.

With that being said, lets move straight onto the main contents.

Prerequisite knowledge

Let me just be frank though: this is not a topic for beginners. Readers should have a strong working knowledge of JavaScript and strong understanding of the following topics.

Since I am assuming that readers have a good working knowledge of JavaScript, I will assume that readers know all the basics of the language such as variable scopes and hoisting.

What is Functional Programming?

Explanation to the Seven Year Old

Okay son, functional programming is like me making a promise like this to you.

Lets say I need that packet of chips you have in your left hand to make something more delicious.

You give me your packet of chips. I work with it.

And as a thank you, I will give you a brand new packet of “more delicious chips”. Don’t worry, I won’t make any changes to your original packet of chips.

Both the original and the new flavored chips are yours to keep okay?

Functional Programming in a Nutshell

Functional programming (often abbreviated FP) is a way of thinking and writing a program,also known as a programming paradigm.

It is the process of building software by composing pure functions, avoiding

  1. shared state
  2. mutable data
  3. side-effects

source: what is functional programming?

 

Functional programming, summed up in tens words is: pure functions, avoid shared state, mutable data and side-effects.

If there is anything that you take away from this tutorial, please take with you those ten words in the previous sentence.

The whole purpose of this tutorial, is to have those words stick with you like glue. It will help wrap your heard around some of the more complex topics related to functional programming.


The art of functional programming is very similar to cooking. When we cook, we follow recipes. We also have different ingredients and ways of preparing each ingredients. If we cook and prepare the dishes in a certain way, we get an expected outcome.

If you are familiar with object-oriented programming, it is a programming paradigm built around objects.

In contrast, in functional programming, we compose function together to get the desired results.

It is more action and logic driven, in contrast to object-oriented programming, which is centered around objects and driven by the data each objects hold.

Functional Programming vs Object-Oriented Programming Example

Okay, the above example may not make sense, so let us explore the difference.

Lets say for example, we are cooking an egg.

 

Naturally, we want a cooked egg from cooking the egg. Here is an abstract illustration of both the functional and object-oriented approach to cooking an egg.

Functional Approach? or is it Procedural?

  • Add oil to the frying pan.
  • Crack the egg open and put it in the pan.
  • Wait a couple of minutes and flip the egg.
  • After another couple of minutes, take out the cooked egg.

In a later section, you will see why I added a question mark in the title for this section.

The functional way of solving problems is through composition. In another words, combining two or more functions to create a new function. In the example above, we are combining the all the actions above to get the result that we want. The output will always be the same as long as we follow that approach, assuming we are entering eggs as the parameter.

Composition in it of itself can be its own post, so I will cover composition in detail in a future post.

In the example above, we are combining the action of adding oil to the frying pan and putting the egg in the pan to create a new action of cooking an egg.

Or are we?????

I apologize.

The previous example was a trick question and is more akin to procedural programming. I added it, because people often don’t understand the difference between procedural and functional programming. Therefore, I took the liberty of making this distinction, which I believe is important for everybody starting out with functional programming to know and fully be aware of.

Procedural programming, in a nutshell, is calling a set of procedures in order. Much like cooking. I.e.

  1. Add oil to the frying pan.
  2. Crack the egg open and put it in the pan

And so on. You get my gist right?

Lets now take a look at the object-oriented approach.

Object-oriented Approach

  • A person should have access to the following items
    • Egg
    • Frying pan
    • oil
  • A person should be able to fry the egg (method).
  • Call a person and ask him/her to fry the egg.
  • You get a fried egg in return.

In contrast to the functional approach, the object oriented approach would be defined in the following way.

  • A person can cook an egg.
  • The person has the required ingredients and equipment (Egg, frying pan, oil).

The object oriented approach is centered around the data and a set of actions/features that each individual object has/is capable of doing.

Although the outcome is the same (a person cooks an egg, you get a fried egg), the approach and way of solving the problem is very different.

Functional Programming Pitfalls in the Egg Cooking Example

In the meanwhile, I want to finally point out that there is something fundamentally wrong with the cooking example. We are violating a key principle in functional programming.

I have dropped hints here and there. Care to guess what that may be?

Click here to find out

Purity. We are altering the state of the egg that was used. By cooking the egg, the original state of the egg is manipulated.

I am going to assume that you know the answer and continue on with my explanation. If you are curious, no shame in clicking the link above to find out.

If we were to get a little bit ‘imaginative’, in the world of functional programming, we would make a clone of an egg and work with the clone of the egg, cook it and eat that, leaving the original egg intact. Something like the procedure shown before.

functional programming illustration clone egg cook

Sounds kind of crazy right?

Remember, in functional programming, we don’t want to create side-effects. We want to preserve the state of the original object that was passed in.

The reason why I wanted to share that wacky outer space example is to give you a proper demonstration of functional programming and how one thinks functionally.

Functional Programming Benefits

Functional programming only has benefits if implemented correctly.

What are some of the benefits of adopting functional programming practices into your code base?

  • If done properly, easier to debug, due to predictable outcomes.
  • Easier to unit test (ties in with above).
  • Results in modular code. We like modular code, because it is reusable.
  • Safer multi-threading thanks to pure functions.

If you don’t want to read through the list, simply put, we like functional programming because if implemented correctly, results in fewer bugs, easily reusable and predictable code.

You might be wondering: what the heck is this concept of pure functions that this guy keeps on mentioning? Hold your horses. I am building excitement so that this concept sticks in your brain for all eternity!!!

Without further ado, I would now like to FINALLY introduce to you …

Pure Functions

Because functional programming is built around action and logic, there is a strong emphasis on building an ecosystem of functions that are pure.

Thus, pure functions form the foundation of functional programming.

A pure function, simply put, is a function that only does what it is supposed to do.

  1. Given a certain input, it will always yield the same result for that input.
  2. The function always returns an original object after performing the operation it is supposed to do.
  3. Does not rely on any external mutable state.

If the technical conditions above doesn’t make sense, just think of it this way.

A pure function only does what it is supposed to do. Nothing more, nothing less.

It returns a new result set that is not tied in anyway to an external item.

It does not change the passed in item.

Make sense? If not, don’t worry. Keep reading. I am certain that by the end of this, you will fully understand and never, ever forget what a pure function is.

Here is a general rule of thumb taken from this great post on pure functions:

A dead giveaway that a function is impure is if it makes sense to call it without using its return value.

For pure functions, that’s a nope.

Pure vs Impure Functions

In theory, the difference between pure and impure functions are quite clear. However, in practice, sometimes, the lines between the two can be quite blurry, especially when one is just starting out.

In this section, we will aim towards clarifying some of the distinctions between the two.

Sometimes, looking at a code snippet makes concepts so much clearer.

Code can often be many times more expressive than information displayed in text format.

Pure Function Case study

First of all, lets look at a very simple function.

function log(input) {
    console.log(input);
}

log("hello");  // logs hello to the console.

I am certain that I don’t have to explain to anybody what the code above does. All it does is simply log onto the console the value that was passed.

However, is the function above a pure function?

Think about the golden rules for a second.

Yes, it was a trick question. Believe it or not, the function above is impure. Why? Lets take a look at each of the key facts that make up a pure function.

  1. Does the function only do what it is supposed to do? Yes, the function is meant to log the input and only does that.
  2. The function returns an original object? No. The function does not return any value.
  3. Does not rely on any external mutable state? No. It is using the console object, which is an external, mutable object.

Do you now see why the previous function is not a pure function?

Let us examine a pure function. This should clarify any lingering uncertainty.

function sum(a,b) {
    return a + b;
}

Lets go through the same checklist with the sum function

  1. Does the function only do what it is supposed to do? Yes, all it does is add the values passed in.
  2. The function returns an original object? Yes. The function returns the result of the sum of the two passed in values.
  3. Does not rely on any external mutable state? Yes. It does not depend on any other objects to perform the add operation.

The function sum(), is therefore, a pure function. Hopefully this makes sense.

Pure Function Example

Lets say for example, you are an artist. You wanted to borrow a friend’s piece of work, so you asked him for a copy of his work.

You use that copy as a reference to produce your own piece of work.

That is a pure function example. Lets examine why though by examining code.

function makeArtwork(workDoneByFriend) {
    var myArtWork = {};
    var key;
    for (key in workDoneByFriend) {
        if (workDoneByFriend.hasOwnProperty(key)) {
            myArtWork[key] = workDoneByFriend[key] + " my added flavor";
        }
    }
    return myArtWork;
}

Your new piece of artwork (based off the friend’s work) does not impact the friend’s artwork in anyway. Not a single stroke or pixel is changed.

It is not relying on any external immutable state. Even if the original copy is manipulated, that change will not affect the copy of the artwork that you have with you. Nor will it make any changes to your fresh new artwork.

The only exception would be if the property being copied over is a reference type. In this case, to avoid possible side effects, people may recommend making deep copies of reference types. In contrast to deep copies, making shallow copies will likely result in unexpected side-effects that may be difficult to find, depending on the size of the application.

Closing Remarks

Functional programming is a very complex subject. Therefore, I will most likely write additional posts in the near future to supplement what was discussed here.

In the upcoming tutorials, we will go through basic functional programming methods such as filter(), map() and reduce(). Hope that this read helped you understand functional programming with greater clarity, especially if you are new to this.

Please feel free to leave any feedback that will help me improve the content. Until next time, happy coding and peace!

About the Author Jay

I am a programmer currently living in Seoul, South Korea. I created this blog as an outlet to express what I know / have been learning in text form for retaining knowledge and also to hopefully help the wider community. I am passionate about data structures and algorithms. The back-end and databases is where my heart is at.

follow me on: