DEV Community

loading...

Functional Programming with JavaScript — Part 3 — The JavaScript you need to know for React!

frontendexp
Mobile and Web development
Originally published at javascript.plainenglish.io on ・8 min read

Agenda
What is functional JavaScript?

  1. Imperative Versus Declarative
  2. Functional Concepts (Immutability, Pure Functions) Part 4 has Data Transformations Higher-Order Functions, Composition, Recursion You will notice that React makes use of functional JavaScript a lot. React, Flux, and Redux all fit within the functional JavaScript paradigm. Understanding the basic concepts of functional programming will elevate your knowledge of structuring React applications. If you are wondering where this functional trend came from, the answer in the 1930s, with the invention of lambda calculus, or λ-calculus.1 Functions can be sent to functions as arguments or returned from functions as results. More complex functions, called higher-order functions, can manipulate functions and use them as either arguments or results or both. In the 1930s, Alonzo Church was at Princeton experimenting with these higher-order functions when he invented lambda calculus.

Photo by Jeswin Thomas on Unsplash
In the late 1950s, John McCarthy took the concepts derived from λ-calculus and applied them to a new programming language called Lisp.
Lisp implemented the concept of higher-order functions and functions as first-class members or first-class citizens.
A function is considered a first-class member when it can be declared as a variable and sent to functions as an argument.
These functions can even be returned from functions.
We are going to go over some of the key concepts of functional programming, and we’ll cover how to implement functional techniques with JavaScript.
What It Means to Be Functional
JavaScript supports functional programming because JavaScript functions are first-class citizens. This means that functions can do the same things that variables can do.
You may have noticed that you can declare functions with the var keyword the same way you can declare strings, numbers, or any other variables:
var log = function(message) {
console.log(message)
};
log(“In JavaScript functions are variables”)
// In JavaScript, functions are variables
With ES6, we can write the same function using an arrow function. Functional programmers write a lot of small functions, and the arrow function syntax makes that much easier:
const log = message => console.log(message)
Since functions are variables, we can add them to objects:
const obj = {
message: “They can be added to objects like variables”,
log(message) {
console.log(message)
}
}
obj.log(obj.message)
// They can be added to objects like variables
Both of these statements do the same thing: they store a function in a variable called log.
Additionally, the const keyword was used to declare the second function, which will prevent it from being overwritten. We can also add functions to arrays in JavaScript:
const messages = [
“They can be inserted into arrays”,
message => console.log(message),
“like variables”,
message => console.log(message)
]
messages1 // They can be inserted into arrays
messages3 // like variables
Functions can be sent to other functions as arguments, just like other variables:
const insideFn = logger =>
logger(“They can be sent to other functions as arguments”);
insideFn(message => console.log(message))
// They can be sent to other functions as arguments
They can also be returned from other functions, just like variables:
var createScream = function(logger) {
return function(message) {
logger(message.toUpperCase() + “!!!”)
}
}
const scream = createScream(message => console.log(message))
scream(‘functions can be returned from other functions’)
scream(‘createScream returns a function’)
scream(‘scream invokes that returned function’)
The last two examples were of higher-order functions, functions that either take or return other functions.
Using ES6 syntax, we could describe the same createScream higher-order function with arrows:
const createScream = logger => message =>
logger(message.toUpperCase() + “!!!”)
From here on out, we need to pay attention to the number of arrows used during function declaration. More than one arrow means that we have a higher-order function.
We can say that JavaScript is a functional language because its functions are first-class citizens. They can be saved, retrieved, or flow through your applications just like variables.
Imperative Versus Declarative
Functional programming is a part of a larger programming paradigm: declarative programming.
Declarative programming is a style of programming where applications are structured in a way that prioritizes describing what should happen over defining how it should happen.

Source: shorturl.at/mIPU3
In order to understand declarative programming, we’ll contrast it with imperative programming, or a style of programming that is only concerned with how to achieve results with code.
Let’s consider a common task: making a string URL-friendly. Typically, this can be accomplished by replacing all of the spaces in a string with hyphens, since spaces are not URL-friendly.
First, let’s examine an imperative approach to this task:
var string = “This is the midday show with Cheryl Waters”;
var urlFriendly = “”;
for (var i=0; i if (string[i] === “ “) {
urlFriendly += “-”;
} else {
urlFriendly += string[i];
}
}
console.log(urlFriendly); // This-is-the-midday-show-with-Cheryl-Waters
In this example, we loop through every character in the string, replacing spaces as they occur.
The structure of this program is only concerned with how such a task can be achieved.
We use a for loop and an if statement, and set values with an equality operator. Just looking at the code alone does not tell us much.
Imperative programs require lots of comments in order to understand what is going on.
Now let’s look at a declarative approach to the same problem:
const string = “This is the midday show with Cheryl Waters”
const urlFriendly = string.replace(/ /g, “-”)
console.log(urlFriendly)
Here we are using string.replace along with a regular expression to replace all instances of spaces with hyphens.
Using string.replace is a way of describing what is supposed to happen: spaces in the string should be replaced.
The details of how spaces are dealt with are abstracted away inside the replace function. In a declarative program, the syntax itself describes what should happen and the details of how things happen are abstracted away.
Essentially, declarative programming produces applications that are easier to reason about, and when it is easier to reason about an application, that application is easier to scale.
Now, let’s consider the task of building a document object model, or DOM.
An imperative approach would be concerned with how the DOM is constructed:
var target = document.getElementById(‘target’);
var wrapper = document.createElement(‘div’);
var headline = document.createElement(‘h1’);
wrapper.id = “welcome”;
headline.innerText = “Hello World”;
wrapper.appendChild(headline);
target.appendChild(wrapper);
This code is concerned with creating elements, setting elements, and adding them to the document.
It would be very hard to make changes, add features, or scale 10,000 lines of code where the DOM is constructed imperatively.
Now let’s take a look at how we can construct a DOM declaratively using a React component:
const { render } = ReactDOM
const Welcome = () => (

Hello World

)
render(
,
document.getElementById(‘target’)
)
React is declarative.
Here, the Welcome component describes the DOM that should be rendered.
The render function uses the instructions declared in the component to build the DOM, abstracting away the details of how the DOM is to be rendered.
We can clearly see that we want to render our Welcome component into the element with the ID of ‘target’.
Functional Concepts
The core concepts of functional programming are the following: immutability, purity, data transformation, higher-order functions, and recursion.
Immutability
To mutate is to change, so to be immutable is to be unchangeable.
In a functional program, data is immutable. It never changes.
Example
var rateColor = function(color, rating) {
return Object.assign({}, color, {rating:rating})
}
console.log(rateColor(color_lawn, 5).rating) // 5
console.log(color_lawn.rating) // 4
Object.assign takes a blank object, copies the color to that object, and overwrites the rating on the copy.
Now we can have a newly rated color object without having to change the original.
We can write the same function using an ES6 arrow function along with the object spread operator.
This rateColor function uses the spread operator to copy the color into a new object and then overwrite its rating:
const rateColor = (color, rating) =>
({
…color,
rating
})
This emerging JavaScript version of the rateColor function is exactly the same as the previous one. It treats color as an immutable object, does so with less syntax, and looks a little bit cleaner.
Notice that we wrap the returned object in parentheses. With arrow functions, this is a required step since the arrow can’t just point to an object’s curly braces. Let’s consider an array of color names:
let list = [
{ title: “Rad Red”},
{ title: “Lawn”},
{ title: “Party Pink”}
]
We could create a function that will add colors to that array using Array.push:
var addColor = function(title, colors) {
colors.push({ title: title })
return colors;
}
console.log(addColor(“Glam Green”, list).length) // 4
console.log(list.length) // 4
However, Array.push is not an immutable function. This addColor function changes the original array by adding another field to it.
In order to keep the colors array immutable, we must use Array.concat instead:
const addColor = (title, array) => array.concat({title})
console.log(addColor(“Glam Green”, list).length) // 4
console.log(list.length) // 3
Array.concat concatenates arrays. In this case, it takes a new object, with a new color title, and adds it to a copy of the original array.
You can also use the ES6 spread operator to concatenate arrays as we have seen before in this article.
addColor function:
const addColor = (title, list) => […list, {title}]
This function copies the original list to a new array and then adds a new object containing the color’s title to that copy. It is immutable.
Pure Functions

Photo by Aaron Burden on Unsplash
Pure Functions
What is a pure function?
A pure function is a function that returns a value that is computed based on its arguments.
Pure functions take at least one argument and always return a value or another function.
They do NOT cause side effects, do NOT set global variables, or change anything about the application state.
They treat their arguments as immutable data.
In order to understand pure functions, let’s first take a look at an impure function:
var frederick = {
name: “Frederick Douglass”,
canRead: false,
canWrite: false
}
function selfEducate() {
frederick.canRead = true
frederick.canWrite = true
return frederick
}
selfEducate()
console.log( frederick )
// {name: “Frederick Douglass”, canRead: true, canWrite: true}
The selfEducate function is not a pure function because it does not take any arguments, and it does not return a value or a function.
It also changes a variable outside of its scope: Frederick.
Once the selfEducate function is invoked, something about the “world” has changed.
It causes side effects:
const frederick = {
name: “Frederick Douglass”,
canRead: false,
canWrite: false
}
const selfEducate = (person) => {
person.canRead = true
person.canWrite = true
return person
}
console.log( selfEducate(frederick) )
console.log( frederick )
// {name: “Frederick Douglass”, canRead: true, canWrite: true}
Pure Functions Are Testable
They do not change any global variables, and therefore do not require a complicated test setup or teardown.
Everything a pure function needs to operate it accesses via arguments.
This selfEducate function is also impure because it causes side effects.
Invoking this function mutates the objects that are sent to it. If we could treat the arguments sent to this function as immutable data, then we would have a pure function.
const frederick = {
name: “Frederick Douglass”,
canRead: false,
canWrite: false
}
const selfEducate = person =>
({
…person,
canRead: true,
canWrite: true
})
console.log( selfEducate(frederick) )
console.log( frederick )
// {name: “Frederick Douglass”, canRead: true, canWrite: true}
// {name: “Frederick Douglass”, canRead: false, canWrite: false}
Finally, this version of selfEducate is a pure function.
It computes a value based on the argument that was sent to it: the person. It returns a new person object without mutating the argument sent to it and therefore has no side effects.
I created a part 4 since this is becoming a long post.
When you feel ready, check out part 4!

Discussion (0)