functional programming - RowinRuizendaal/frontend-data GitHub Wiki

Functional programming

Functional programming (FP) is the process of building software by composing pure functions, avoiding shared state, mutable data, and side effects. Functional programming is declarative rather than imperative, and the application state flows through pure functions. Contrast with object-oriented programming, where applications state is usually shared and colocated with methods in objects.

  • Pure functions
  • Function composition
  • Avoid shared state
  • Avoid mutating state
  • Avoid side effects

A pure function is a function which:

  • Given the same inputs, always returns the same output
  • Has no side-effects

Function composition

is the process of combining two or more functions in order to produce a new function or perform some computations. For example, composition f. g is equivalent to f(g(x)) in javascript.

Shared state

A shared state is any variable, object, or memory space that exist in a shared scope, or as the property of an object being passed between scopes. A shared scope can include global scope or close scopes, Often, in object-oriented programming, objects are shared between scoped by adding properties to other objects.

// With shared state, the order in which function calls are made
// changes the result of the function calls.
const x = {
  val: 2
};

const x1 = () => x.val += 1;

const x2 = () => x.val *= 2;

x1();
x2();

console.log(x.val); // 6

// This example is exactly equivalent to the above, except...
const y = {
  val: 2
};

const y1 = () => y.val += 1;

const y2 = () => y.val *= 2;

// ...the order of the function calls is reversed...
y2();
y1();

// ... which changes the resulting value:
console.log(y.val); // 5

Immutability

An immutable object is an object that can't be modified after it's created. Conversely, a mutable object is any object which can be modified after it's created.

Immutable objects can’t be changed at all. You can make a value truly immutable by deep-freezing the object. JavaScript has a method that freezes an object one-level deep:

const a = Object.freeze({
  foo: 'Hello',
  bar: 'world',
  baz: '!'
});

a.foo = 'Goodbye';
// Error: Cannot assign to read-only property 'foo' of object Object

But frozen objects are only superficially immutable. For example, the following object is mutable:

const a = Object.freeze({
  foo: { greeting: 'Hello' },
  bar: 'world',
  baz: '!'
});

a.foo.greeting = 'Goodbye';

console.log(`${ a.foo.greeting }, ${ a.bar }${a.baz}`);

Side effects

A side effect is an application state change that is observable outside the called function other than its return value. Side effects include:

  • Modifying any external variable or object property
  • Logging to the console
  • Writing to the screen
  • Writing to a file
  • Writing to the network
  • Triggering any external process
  • Calling any other functions with side-effects

High order functions

High order functions are functions that operate on other functions either by taking them as arguments or by returning them, in simple words, A Higher-order function is a function that receives a function as an argument or returns the function as output.

  • Array.prototype.map
  • Array.prototype.filter
  • Array.prototype.reduce

Array.prototype.map

The map() method creates a new array by calling the callback function provided as an argument on every element in the input array. The map() method will take every returned value from the callback function and creates a new array using those values.

without

const arr1 = [1, 2, 3];
const arr2 = [];
for(let i = 0; i < arr1.length; i++) {
  arr2.push(arr1[i] * 2);
}// prints [ 2, 4, 6 ]
console.log(arr2);

With

const arr1 = [1, 2, 3];
const arr2 = arr1.map(item => item * 2);
console.log(arr2);

Array.prototype.filter

The filter() method creates a new array with all elements that pass the test provided by the callback function. The callback function passed to the filter() method accepts 3 arguments: element, index, and array.

without

const persons = [
  { name: 'Peter', age: 16 },
  { name: 'Mark', age: 18 },
  { name: 'John', age: 27 },
  { name: 'Jane', age: 14 },
  { name: 'Tony', age: 24},
];

const fullAge = [];
for(let i = 0; i < persons.length; i++) {
  if(persons[i].age >= 18) {
    fullAge.push(persons[i]);
  }
}console.log(fullAge);

With

const persons = [
  { name: 'Peter', age: 16 },
  { name: 'Mark', age: 18 },
  { name: 'John', age: 27 },
  { name: 'Jane', age: 14 },
  { name: 'Tony', age: 24},
];
const fullAge = persons.filter(person => person.age >= 18);
console.log(fullAge);

Array.prototype.reduce

The reduced method executes the callback function on each member of the calling array which results in single output value. The reduce method accepts two parameters: 1) The reducer function (callback), 2), and an optional initialValue.

without

const arr = [5, 7, 1, 8, 4];
let sum = 0;
for(let i = 0; i < arr.length; i++) {
  sum = sum + arr[i];
}// prints 25
console.log(sum);

with

const arr = [5, 7, 1, 8, 4];
const sum = arr.reduce(function(accumulator, currentValue) {
  return accumulator + currentValue;
});// prints 25
console.log(sum);

sources

Arora, S. (2019, March 27). Understanding Higher-Order Functions in JavaScript - Bits and Pieces. Medium. https://blog.bitsrc.io/understanding-higher-order-functions-in-javascript-75461803bad

Elliott, E. (2019, July 2). Master the JavaScript Interview: What is Functional Programming? Medium. https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0