Functional Programming in JavaScript(ES6+): map, filter

Woohyun Jang
Nov 18, 2020 · 4 min read
Functional Programming

Before We Start With Function Programming

Before we start with Functional Programming, let’s talk about Modern software programming. In modern society software products are increasing both quantitatively and qualitatively. Hardware performance continues to improve as well.

To satisfy users who become more demanding, our software should provide more fun, more creative, and more convenient user experience.

Modern software handles larger volumes, reflects real-time changes more immediately, and needs to be more accurate. So the complexity of the code to implement this is higher.

There are paradigms to make a program that is responsive to usability, performance, scalability, and planning changes.

Function Programming

Functional Programming(FP) is a paradigm that consists(combines) the solution of a problem with verbs(functions).

Functional programming makes the application, the components of a function, and the language itself look like a function. and puts the concept of functions first.

FP increases reusability(combination) through modularization and improved productivity through this.

Pure and first-class functions are used to reduce errors and increase stability by minimizing side effects.

Pure functions

  • If the same argument is given, the same result is returned
  • No side effect. It has no effect other except the return value
  • The timing of the evaluation is not important. It always has the same result when called
// Pure function
function pureAdd(a, b) {
return a + b;
}
// Impure functionlet a = 1;
function imPureAdd(b) {
a + b
}

First-class functions

  • First-class functions can handle the function as a value
  • Functions can be assigned to a variable, passed as an argument, or returned as a result.
// assigned to a variableconst getWorld = () => {
return 'World';
}
// passed as an argumentfunction sayHello(getName) {
console.log('Hello, ' + getName());
}
sayHello(getWorld);

Map, Filter

We’ll be going to make some FP style utility functions ‘map’ and ‘filter’.

map & filter functions are very useful function in programming. you can use them in like ‘Lodash.js’, ‘Underscore.js’

Map

The ‘map’ function takes two arguments collection and iteratee. It creates a new array of values by running each element in the collection thru the iteratee.

The iteratee is called for each element and returns a calculated new value.

I made some mock data for the test and described the test case. In this case, the map function gets usersMock as a collection and returns their ids. So we expect to return [1, 2, 3, 4, 5, 6].

function map(collection, iteratee) {  const result = [];  for (const value of collection) {    result.push(iteratee(value));  }  return result;}module.exports = map;

So the map function put the iteratee’s result to result traversing every elements.

Then the test case successes!

Filter

The filter function filters the collection according to predicate.

If we want to get a new array that only older than 20 in usersMock, we can write the test case like that.

test('filter', () => {  expect(filter(usersMock, ({ age }) => age > 20).length).toBe(4);});

To succeed in that test case, we have to put the element only corresponding to the predicate traversing all elements like map function.

function filter(collection, predicate) {  const result = [];  for (const value of collection) {    if (predicate(value)) {      result.push(value);    }  }  return result;}module.exports = filter;

Combine functions

Now that let’s solve the more complex question. If we want to get the user’s ids only younger than 30, how can I code it?

test('filter and map', () => {  function solution(collection) {
// answer
} expect(solution(usersMock)).toStrictEqual([1, 2, 3, 4, 6]);});

Without functional programming, we can make the solution function like that.

function solution(collection) {  const result = [];  for (const value of collection) {    const {id, age} = value;    if (age < 30) {      result.push(id);    }  }  return result;}

We can check the predicate while cycling, and put the element’s id to result. This solution works well, but as requirements get more complex, code will be difficult to read, difficult to maintain, and less reusable.

We already have two functions map&filter. we may implement the solution with them.

function solution(collection) {  return map(    filter(collection, ({age}) => age < 30),    ({ id }) => id,  );}

In this code, the solution returns the map function’s result. The map function takes the filter’s result as a collection and it also takes the mapper that returns the user’s id.

So the map function will take the filtered collection and it’ll return the filtered collection by id.

Let’s compare the two solutions. FP is more readable and easy. If someone sees FP style solution, he can understand the code’s purpose easily. He can think just like that ‘map the filtered collection’!

The one more powerful thing about FP is reusability. The solution function consists of the map & filter functions.

When new requirements come in(ex. please give me the array of user’s names older than 25), we can use map & filter functions again and again.

Functional Programming is implemented by the combination of functions so it helps in safe and productive development.

Source Code

The Startup

Get smarter at building your thing. Join The Startup’s +737K followers.