Become a functional JavaScript hero ✨

Fredrik Jensen
Frontend Weekly
Published in
4 min readJan 14, 2017

For the last year i have been trying to level up my JavaScript skills. Maybe the most useful thing I have learned is composition. Being able to write code that reads well is awesome, both for us and and the poor fellow that may going to maintain the code once in the future.

I ❤️ ES6. The syntax is so much nicer than old style JavaScript. And even the bad reputation JavaScript had back in the days is about to disappear. Methods like map, filter, reduce is not only non-mutable methods, but they reads well too. But you can still go wrong. And it is quite easy to go wrong with JavaScript. So choosing a code style and jump on the functional JS hipster wagon could might be a good idea!

So let’s go ahead. Say we have this chunk how old-style JavaScript:

function completedTodos(todos) {
var completedTodos = [];
for (var i = 0; i < todos.length; i++) {
if (todos[i].completed) {
if (completedTodos.length < 10) {
todos[i].image = './path/image.jpg';
completedTodos.push(todos[i]);
}
}
}
return completedTodos;
};

Apart from the old syntax the the function could look quite good at first sight. It is not that long and it seems quite clean. But it is not. First it mutates two times: Assigning properties directly on the todos array and the push method are mutating too. But we are not going to concentrate on mutating this time, we are saving that for later. We are going to concentrate on decomposition.

So lets look at what the function actually do: It returns the last ten completed todos and adds an image to them. First of all the function name completedTasks is not very describing of what it actually does and more important is quite hard to read from the code what it actually are doing. And having readable self explaining code is quite valuable. Functional programming is a lot about that. Telling a story, one function at a time.

To decompose this function let’s start with thinking about which steps we need to accomplish what we want:
• Find all completed todos
• Filter out the last ten
• Add an image to each todo

So, I will write three new functions with the ES6 syntax:

const completedTodos = todos => todos.filter(
todo => todo.completed
);
const firstTenTodos = todos => todos.slice(0, 10);const addImageToTodos = todos => todos.map(todo => {
return {...todo, image: './path/image.jpg'}
});

This is so much nicer. The function names are specific about what the function do, and even if your are not familiar with the syntax, it is quite readable what the methods do too. First we filter to get the completed todos, we slice the last 10 and then we map over each object and add an image. In addition there is no mutating going on, just beautiful pure functions returning new objects. Great! 🎉

So now we are going to compose our functions together. We could to in vanilla JS like this:

cont addImageToFirstTenCompletedTodos = 
addImageToTodos(firstTenTodos(completedTodos(todos)));

But I do not like that. We need to read the function from inside-out, or from right to left to get it. That’s not very readable! Instead I am going to use a little helper called Lodash Flow. It will do exactly the same but from left to right and the syntax is much nicer.

import flow from 'lodash/flow';const addImageToFirstTenCompletedTodos = flow(
completedTodos,
firstTenTodos,
addImageToTodos,
)(todos);

You see? This is just the list we had in the beginning 👌

Bonus: We can now write tests!

When we are doing things this way it is also much easier to write tests. Unit tests could be scaring if you are new to JavaScript, but they are actually quite awesome! I will use Jest for the example, but there are several other great test runners out there too.

So we are going to write a test for our completedTodos function. We have already made the function so we are just importing it, the test it selfs is just a few lines of code. But we need to write some test data:

import 'completedTodos' from '../functions/completedTodos';var todos = [{
name: 'One',
completed: true,
}, {
name: 'Two',
completed: false,
}, {
name: 'Three',
completed: true,
}
];
var result = [{
name: 'One',
completed: true,
}, {
name: 'Three',
completed: true,
}
];
describe('firstTenTodos', () => {
it('Takes and array of todos and returns the completed', () => {
expect(completedTodos(todos)).toEqual(result);
});
});

The only thing we need to do is to describe how our data looks and how we want the result to be. Then we put our function inside expect and our expected result inside toEqual. Then we need to give our test collection and test a name and we are ready to hit npm run test. Easy peasy 🙌

If your test fails, it will log out the difference between what your function are returning and your desired result. So, if we are working with complex data structures it is a good idea to write the test first and run the test while your are developing until your function returns what you want.

So, I am far from a functional JavaScript hero myself. But I really enjoy learning and see my code getting better. And while the frontend world moves quite fast these days, it feels quite nice to learn and use these old proven computer science principles of functional programming.

--

--