Functional Programming in JavaScript
Cristian Salcescu
Copyright 2020 Cristian Salcescu
August 2020 First Edition
Table of contents
Introduction
Functional programming is becoming more popular and this book aims to bring clarity on how to use JavaScript as a functional language.
It turns out that JavaScript has everything it needs to be used as a functional language. We just need to remove features from the language.
In essence, we are going to remove the this keyword from our code. That means we are not going to use classes or methods using the this keyword. It also implies not using custom prototypes.
Removing this has other benefits. this is the source of much confusion in JavaScript, mainly because it depends on how the function is invoked, not where the function is defined. There are many situations where this points to an unexpected function context and that leads to bugs. By removing this all the related problems are gone.
JavaScript is both a functional programming language and a prototype-based language. If we get rid of this , we are left with JavaScript as a functional programming language. That is even better.
That being said, we can remove this from our code by enabling linting.
Here is an example of a lint configuration file disabling the this keyword from an application built with Create React App .
{
"extends": ["react-app"],
"plugins": [
"immutable"
],
"rules": {
"immutable/no-this": "error"
}
}
JavaScript without this looks like a better functional programming language.
Source Code
The project files from this book are available at https://github.com/cristi-salcescu/functional-programming-in-javascript .
Feedback
I will be glad to hear your feedback. For comments, questions, or suggestions regarding this book send me an email to . Thanks in advance for considering to write a review of the book.
Setup
First, we need to setup our development environment to use the latest JavaScript features.
Package Manager
A package manager is a tool used to track project dependencies in an easy to use manner. At the time of writing, Node.js package manager, in short npm , is the most popular. Lets start by installing Node.js .
The following commands can then be used in command prompt to check the Node.js and npm versions:
node --version
npm --v
NPM Packages
With npm we can install additional packages. These packages are the application dependencies.
The package.json file stores all the node packages used in the project. These packages are the application dependencies. The application can be shared with other developers without sharing all the node packages. Installing all the packages defined in the package.json file can be done using the npm install command.
Start by creating a package.json file using npm .
npm init
We need a tool that converts our JavaScript code into a backward-compatible version and has support for modules . We need Babel . Go and install the necessary packages.
npm install @babel/core @babel/node @babel/preset-env --save
The installed packages can be found in the node_modules folder. The --save flag tells npm to store the package requirement in the package.json file.
In order to use the latest JavaScript, we need to enable a preset. Create the .babelrc file and enable the babel/preset-env preset.
{
"presets": ["@babel/preset-env"]
}
Linting
Linting is the process of analyzing the code for potential errors and stylistic problems. A linter is a tool that runs and reports these problems. Linters are also useful for code formatting and for using best practices.
We are going to use ES Lint . Start by installing it.
npm install eslint --save-dev
Lint rules can be defined in a configuration file named .eslintrc.*
Next, set up a configuration file.
npx eslint --init
One plugin we are going to use is eslint-plugin-functional so lets install it.
npm install eslint-plugin-functional --save-dev
Now go to the .eslintrc.json config file an write the lint rule that forbids the usage of this keyword.
{
"plugins": [
"functional"
],
"rules": {
"functional/no-this-expression": "error"
}
}
Here is how you can run linting on all files inside the src folder.
npx eslint src
In an application created with Create React App we can force linting before starting the development server by prepending the npx eslint src command followed by && .
"scripts": {
"start": "npx eslint src && react-scripts start"
}
Using && means that things on both sides of the && must evaluate to true . If the command on the left side fails the command on the right side will not execute, so in our case, the development server wont start.
IDE
For code editing, we need an Integrated Development Environment, IDE in short.
I am going to use Visual Studio Code but feel free to use any editor you prefer.
In order to write commands open the application folder in Visual Studio Code. Then open the terminal from Terminal -> New Terminal and execute the command.
To run the code inside the filter.js file for example, and check the results, we can just use the following command.
npx babel-node filter.js
For instant linting feedback we can install the ESLint extension for VSCode . Linting allows us to work in a better subset of JavaScript.
Chapter 01: Primitives
We start our learning journey by looking at the first kind of values available in the language.
Primitives
The primitive values include numbers, strings, booleans, null , and undefined . Log some of these primitive values in the console.
console.log(1);
console.log('text');
console.log(true);
All these primitive values have a type. We can find the type of a value using the typeof operator. Check some of them.
console.log(typeof(1));
//"number"
console.log(typeof(''));
//"string"
console.log(typeof(true));
//"boolean"
There are two number types Number and BigInt . Mainly we are going to use the first one which stores double-precision floating-point numbers. It is important to know that floating-point arithmetic is not accurate.
console.log(0.1+0.2);
//0.30000000000000004
console.log(0.1 + 0.2 === 0.3);
//false
The integer arithmetic is accurate up to 15 digits. We can solve the problem above by first multiplying and then dividing.
console.log(1 + 2 === 3);
//true
console.log(0.1 * 10 + 0.2 * 10) / 10 === 3);
//true
BigInt is used to represent larger numbers. We can create such numbers by appending n to the end of an integer literal.
console.log(12345678987654321n);
Strings are texts. There are three ways to define a string value, single quotes, double quotes and backticks.
"text"
'text'
`text`
Undefined is a type with one value undefined . Null is a type with one value null . Boolean is a type with two values true and false .
Methods on Primitives
Primitives are not objects but they seem to behave like objects because they have methods. For example, we can call the toLowerCase method on a string primitive. How is that possible if a string is not an object? JavaScript creates a wrapper object and destroys it in order to run the toLowerCase method.