DEV Community

Cover image for Why Learning Functional Programming in JavaScript Will Make You a Better Developer
Simon Egersand ๐ŸŽˆ
Simon Egersand ๐ŸŽˆ

Posted on โ€ข Edited on โ€ข Originally published at prplcode.dev

3 1

Why Learning Functional Programming in JavaScript Will Make You a Better Developer

Functional programming (abbreviated as FP) is a programming paradigm that's popular in JavaScript. JavaScript treats functions as first-class citizens and this makes it easy to write functional programming in JavaScript.

This post will tell you the basics and benefits of functional programming and how to use them in JavaScript.

What is Functional Programming?

Functional programming is a way of writing software with specific principles. The idea is that these principles will

  • Make it easier to write, test, and debug the code
  • Make it easier to reason about the code
  • Improve developer productivity
  • And more

Core Principles in Functional Programming

Pure Functions

Functions should be pure. Pure functions always produce the same output and have no side effects affecting the output. Side effects are anything that's outside the control of the function. E.g. any input/output (I/O) such as reading from a database/file or using console.log. Or even a static variable.

Here's a simple example

// This function is pure because it's determinisic.
// It has no side effects.
// Nothing outside the function can influence the output.
// addTen(5) will _always_ be 15
const addTen = input => {
return input + 10;
};
// Fetch the number from the database
const numberFromDb = DB.getNumber();
// This function is not pure because it's not deterministic.
// It has a side effect (the numberFromDb value).
// We cannot know for sure that the outcome will be the same
// every time we call it, and that's why it's not pure
const addWithNumberFromDb = input => {
return input + numberFromDb;
};
view raw fp_js_1.js hosted with โค by GitHub

But I Need I/O?

An application without I/O is not that useful. Functional programming is not about eliminating I/O. Instead, you should separate the business logic from I/O. Any side effects should be handled at the edges of our processes, and not in the middle of them. By doing this you achieve pure business logic that is easily testable.

JavaScript is not a purely functional programming language. So there's nothing from stopping you doing whatever you feel comfortable with though. Haskell, on the other hand, is an example of a purely functional programming language. In Haskell, you're enforced to use the functional programming principles.

Immutable State

Immutable state means that the state should not change. Instead of changing the state, in functional programming we copy it. This might seem counter-intuitive: why would we want to copy state instead of changing it?

In JavaScript, you can pass values by reference. This can be dangerous. Let's look at an example.

// Create a person with a name
let simon = {"name": "simon"};
// Instead of copying simon, we assign it by reference.
// This is dangerous and can have unwanted behavior later.
let lisa = simon;
// Set the correct name of lisa
lisa.name = "lisa";
// But now we also updated simon's name!
console.log(simon); // { name: 'lisa' }
// If we would have copied simon, this would not have happened
// Let's see how we would do it in functional programming
let beth = {"name": "beth"};
// Copy beth instead of using a reference to it
let andy = {...beth};
// Set the correct name of andy
andy.name = "andy";
// Now both variables have the correct name
console.log(andy); // { name: 'andy' }
console.log(beth); // { name: 'beth' }
view raw fp_js_2.js hosted with โค by GitHub

Recursion

With recursion, lists are not iterated using for, while, or do...while because they mutate state (increasing the counter, for example). Instead, in functional programming functions such as map(), filter(), and reduce() are used.

The word "recursion" scared me for a long time, I have to admit. But in JavaScript, you can quickly see the benefits of readability and productivity using these functions.

Let's look at an example!

// A list of fruit, and their price
const fruit = [
{name: 'banana', price: 5},
{name: 'apple', price: 3},
{name: 'pear', price: 7}
];
// Now we want to increase the price of all fruit
// Let's do this using a for loop
// NOTE: We're also mutating state here,
// which as you know can be dangerous
for (f of fruit) {
f.price = f.price + 5;
}
// Instead, let's use map()
const moreExpensiveFruit = fruit
.map(f => {
return { ...f, price: f.price + 5 }
});
// Now we're using functional programming!
// 1. We're not mutating fruit, instead we're copying data with the spread operatator `...`
// 2. map() returns a new list, so the fruit list is still unchanged
view raw fp_js_3.js hosted with โค by GitHub

Functional Programming in JavaScript

I showed you briefly how to use map() already. Let's dig into it some more.

map() iterates over your list, one element at a time, and lets you replace it with something new. This is useful for updating a value for all elements in a list, for example. It then returns a new list, leaving the old one unmodified. So it follows the functional programming principle of not modifying state.

And there are two more functions you should know about, filter() and reduce().

filter() will let you filter out unwanted elements from a list. This is useful for removing elements that meet certain criteria from a list. E.g. "filter out fruit that's more expensive than 5. And just like map(), it returns a new list.

// A list of fruit, and their price
const fruit = [
{name: 'banana', price: 5},
{name: 'apple', price: 3},
{name: 'pear', price: 7}
];
// We use filter() to say
// "only include fruit that has a price of 5 or less"
const cheapFruit = fruit
.filter(f => f.price <= 5);
// Log the result to see that "pear" was filtered out
console.log(cheapFruit); // [ {name: 'banana', price: 5}, {name: 'apple', price: 3} ]
view raw fp_js_4.js hosted with โค by GitHub

reduce() will let you "reduce" a list of elements into a single value. This is useful for working with numbers.

// A list of fruit, and their price
const fruit = [
{name: 'banana', price: 5},
{name: 'apple', price: 3},
{name: 'pear', price: 7}
];
// We use reduce() to get the "total price of all fruit"
const sumPriceFruit = fruit
.reduce((previous, current) => previous + current.price, 0);
// Log to see the result
console.log(sumPriceFruit); // 15
view raw fp_js_5.js hosted with โค by GitHub

This function was the hardest one to understand for me. I recommend you check out the MDN Web Docs about it.

Conclusion

Now you know what functional programming is about, why it's useful, and how to use it in JavaScript. It might take some time to get used to but it's well worth the effort. The functions we covered are available in all major programming languages. This is not something specific to JavaScript.


Connect with me on Twitter, LinkedIn, or GitHub

Originally published at prplcode.dev

Top comments (0)

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more