An Introduction to Functional Programming Style in JavaScript

Ghost Together
7 min readNov 29, 2018

--

Here’s a list of my best web development tutorials.

Complete CSS flex tutorial on Hashnode.

Ultimate CSS grid tutorial on Hashnode.

Higher-order functions .map, .filter & .reduce on Hashnode.

You can follow me on Twitter to get tutorials, JavaScript tips, etc.

Follow me on Twitter for JavaScript tips and book announcements.

In recent years there has been a tectonic shift happening between traditional programming and Functional Programming style in JavaScript. It’s not about one being better than the other but simply a personal preference.

You’ll get the most out of this article if you’re coming to the world of FP for the first time ever. It’s just a demonstration of basic principles.

What is Functional Programming all about in general?

  1. Clean CodeYour program is easy to read and therefore maintain.
  2. Syntactic Efficiency — The problem your code is trying to solve is expressed with less code but without sacrificing its function.
  3. More Abstract — Instead of thinking about the logic of a for-loop, your program will look more abstract, almost symbolic, like a math equation.
  4. Automatic Reduction of Common Errors — simply developing a FP mindset will automatically prevent you from bumping into some of the most commonly overlooked programming errors and traps.
  5. Do More In Less Lines Of Code — Your code will look significantly shorter than its traditional style equivalent.

This actually sounds good!

Yes — FP will require of you a change in how you think about code. But it is often used in real world production environments working on a team of software engineers where efficiency and code maintenance matter.

Imagine being hired and the lead developer is a huge fan of FP? Instead of having to force-learn the FP style you can get a bit of a head start if you take the time to understand the basics.

Things To Expect From Functional Programming In Practice

Let’s take a look at this simple for-loop:

let LIST = [1, 2, 3];// Part 1: for-loop as an iterator / increment-er
for
(let i= 0; i< LIST.length; i++) {
// Part 2: the statement to execute on each iteration
LIST[i] = LIST[i] + 1;
}
console.log(LIST); // [2, 3, 4]

We have taken a list, passed it through a two-fold process of iterating over a set of items in the array, and incremented each value by one. Thus taking the original value [1,2,3] and turning it into [2,3,4].

Fair enough. This isn’t Google search algorithm.

But it works as an example of a traditional iterator using the famous for-loop.

Pure Functions

You can’t talk about Functional Programming without mentioning anything about pure functions. But what is a pure function?

The purpose of a pure function is to reduce side effects.

A side-effect in a computer program can occur when you write functions that return unpredictable results or affect data outside of function scope in unpredictable ways — risking the chance of mangling program state.

Once your program state is mangled, it might wreak chaos on the integrity of your program reducing its overall quality. One error leads to another and you become unaware why bugs are even happening anymore. No one wants that.

But…a pure function is not a language feature. It is designed by the programmer in such way as to return predictable results given a specific set of arguments. For example 1 + 2 will always return 3.

On the other hand Math.random() cannot be a pure function. By design it returns a random number each time.

Function Purity is often determined by its return value.

So if your function returns an unpredictable value — even though you’re passing the same (unchanging) set of arguments to it — it can be said that you have created an impure function.

// Pure - returns same value using same arguments
function
sum(a, b) { return a + b; }
// Impure - returns random values regardless what is passed to it
function
sum(a, b) { return Math.random() * (a + b); }

Can you stick to writing pure functions? If so you are one step closer to becoming better at functional programming style.

Function purity might not make a lot of sense at first. Especially without a concrete example. But a computer program is not a blatant list of statements. Things you do inside functions may affect overall program state.

Keep in mind though: you can never create an entirely pure program. But if you stick as close as possible to purity it will help you down the road to avoid many common errors that would have happened if you weren’t paying attention to these types of rules. It’s a habit and a discipline.

It will start making a lot more sense when you see it combined with other Functional Programming style principles.

Let’s Rewrite Our For-Loop To Functional Style

Let’s utilize the array’s map method to rewrite our for-loop.

let LIST = [1, 2, 3];LIST.map( function(item) { return item + 1; } );

But wait. In EcmaScript 6, which adds features that specifically support Functional Programming paradigm, you can use an arrow function. An arrow function further reduces the amount of code written:

LIST.map( (item) => { return item + 1; } );

This can be further turned into the following form by removing return:

LIST.map( (item) => item + 1 );

It still works just the same. But looks shorter. More functional. Here functional doesn’t mean that we are using JavaScript functions. But that our code is starting to look more like a mathematical equation. Go figure.

Arrow functions still return the value inside {} as long as it is expressed in a single statement. You can even take it further by removing ():

LIST.map( item => item + 1 );

Remember the for-loop from before? The same exact thing. One statement.

But I should probably say it is almost exactly the same thing.

Arrow functions conceal the value to their scope. This is also a flavor of functional programming. But it means one thing. The original values in the array will not be added to! We still end up with [1,2,3].

And this is to be expected from map method:

let LIST = [1,2,3];LIST.map( item => { item + 1 });console.log(LIST); // still: [1,2,3] nothing incremented!

Let’s move out the function from the map method and store it separately:

let LIST = [1,2,3];let add = item => item + 1;LIST.map( add );console.log(LIST); // still: [1,2,3] nothing incremented!

This looks a bit cleaner. But still our list is not incremented.

This is the paradigm shift. We need to figure out — why not?

The reason that the list is not incremented is because map does not mutate the list in place. It returns a copy of the list with the callback applied to each of its elements. To capture the incrementation all we need to do is assign LIST.map( add ) to a variable as in the following example:

let copy = LIST.map(add);

Now the copy stores incremented values. But… it’s no longer the same array we started with. Which is also a good thing.

Remember how we talked about side effects earlier? The arrow function contains the code within itself without leaking out into global scope or messing with the actual values in the original array. But in Functional Programming this is a good thing. It should be expected.

This is purity at work! And yes it does limit us. But it makes code less sloppy. And we still get a copy of the original array.

There’s More To FP Than Meets The Eye

Functional Programming is not simply converting for-loops into smaller and shorter expressions. There is a lot more to it. For example like in the above code the map & arrow function conceal the item to its own scope.

Array has a bunch of methods on it that oblige the FP style.

One of them is called reduce. If we can combine map and reduce, we can finally produce the effect of working with array’s items in a way where they can be modified without having to be seen by global scope. This conceals the logic of our program to an isolated island (a good coding practice).

let LIST = [1,2,3];
let add = item => { return item + 1 };
let sum = (A, I) => { return A + I };
let val = LIST.map(add).reduce(sum, 0);
console.log( val ); // 9

We can also remove return and {} without breaking the code:

let LIST = [1,2,3];
let add = item => item + 1;
let sum = (A, I) => A + I;
let val = LIST.map(add).reduce(sum, 0);
console.log( val ); // 9

Again, this looks a lot more like a math equation (function). Hence, Functional Programming. Not to be mixed up with JavaScript functions! Which appear to have gradually vanished as we kept on applying FP style.

Reducers are functions that “reduce” your result by following a particular rule. As a programmer you choose what it should be. Here, this rule is expressed in the sum function as A + I. That is, Accumulator + Item. Essentially, this is what our for-loop was doing earlier.

An accumulator is inherent to a reduce operation. It’s exactly what it sounds like. The accumulator keeps track of the compound effect of the operation.

The second parameter of reduce is set to 0. This sets the accumulator to 0.

This way we are starting with 0 in the counter. Once this code is complete this accumulator will become the return value. (Stored in variable val.)

As the code runs, we keep adding the value using this new sum function.

The result is 9.

Because we first added 1 to [1,2,3] and produced [2,3,4].

Then we ran reducer on it to add up all values in [2,3,4] together and return.

And so finally 2+3+4 = 9.

So you can see here how it’s just a slightly different mentality than a for-loop.

Code looks less ugly this way. And it works almost like a math formula.

The Video Tutorial

Check out my video tutorial about Functional Programming Style in JavaScript:

Functional Programming Style

Note: much like this article — this is just an intro created for someone diving into the subject of FP for the first time and not an entire course or a comprehensive study of Function Programming.

Many of my tutorials are written for first time beginners. Like this one. I wrote this tutorial as an introduction to Functional Programming style. Not as an explanation of the entire FP paradigmwhich is so much more.

Not everyone will like FP. But if you do, it is probably a good idea and look beyond map and reduce methods. Good luck out there!

Still available — Grab a copy of CSS Visual Dictionary here in PDF format.

--

--

Ghost Together
Ghost Together

Written by Ghost Together

Ghost Together @ https://semicolon.dev is an alternative to Twitter. Sign up to meet other makers of things.

Responses (10)