Laptop screen with a lot of code

Functional Style Mind Shift in JavaScript

In this article, I would like to show you a few examples of how ECMAScript 5.1 changed the way I write code and how I learned to prefer, readable, maintainable, and functional code over the lame old-school procedural (but sometimes more performant) code.
  • functional
  • javascript

This is a repost of an article I have written in 2014 and many code examples could be written differently with today’s standards of JavaScript.

In my job as a front-end developer and consultant, I speak to other developers a lot about how to write code. Let’s be honest, actually, there is no holy grail of how to write code. There are different opinions and just many factors like stability, re-usability, maintainability, code scannability (which is also very subjective), performance, testability, beautifulness (Admit it! Sometimes you just prefer sexy beautiful code over efficient code!) and probably many many more. However, I strongly believe, that a few of these factors are more important than others depending on the context. While talking to developers and performing JavaScript code reviews at clients, I always figured out that people who adopted a more functional style of writing JavaScript created much more readable, maintainable, and efficient code.

Okay, so let me actually show you a very basic example. Here is a very basic for loop with length catching for better performance:

for (var i = 0, len = names.length; i < len; i++) {
  console.log(names[i]);
}

This coding style is probably best for high-performance parts of your application, however, let be honest here. How many times do you need to loop over arrays where those performance differences get important? If you’re just iterating over the open projects of your logged-in user or the 200 locations on your customers’ map, performance effects from different coding styles might never be a real issue.

So let’s forget about performance here and make our loop a bit more readable and maintainable.

for (var i = 0; i < names.length; i++) {
  console.log(names[i]);
}

Okay, that’s a very basic loop and probably what I see most when looking at code in code reviews at clients.

So what if we’d like to take advantage of the fact that JavaScript works with closures and function expressions. We can even make this more human-readable and maintainable (as we can neglect

names.forEach(function(name) {
  console.log(name);
});

Already known to all the jQuery kids and lodash gurus, the forEach Array Extra in ECMA Script 5.1 will execute our function expression for each element in the array. Isn’t that just pure eye candy? The folks who are yawning bored should probably scroll down at this point to the more advanced examples. The point I want to make here is that using functional style JavaScript is much more human-readable and therefore also much more maintainable. In terms of performance, we would probably run into a problem here if we need to iterate over our big data array with 2 billion objects *cough*… Functional style is generally slower as there is a new closure created for every element in the array (which by the way is also a very nice side effect!). A functional loop is currently (tested in Chrome 36 32-bit on Windows 7 64-bit) 80% slower than a plain for loop but browsers are getting better and better with closure optimization.

So let’s move on to some more advanced examples. Also, a very common practice I regularly see is something similar to this:

var names = ['Anton', 'Bob', 'Phil', 'Ana', 'Eve'],
    namesWithLetterA = [],
    i;
 
for(i = 0; i < names.length; i++) {
  if(names[i][0].toLowerCase() === 'a') {
    namesWithLetterA.push(names[i]);
  }
}
 
console.log(namesWithLetterA);
// Will output ["Anton", "Ana"]

ECMA Script 5.1 gives us a nice Array Extra called filter. It allows you to specify a function that should be used to evaluate if an element should be considered to be part of a filtered version of the array or not. The above example can be simplified a lot with functional style JavaScript:

var names = ['Anton', 'Bob', 'Phil', 'Ana', 'Eve'];
 
console.log(names.filter(function(name) {
  return name[0].toLowerCase() === 'a';
}));
// Will output ["Anton", "Ana"]

Look at this! Again, we can simplify our code a lot and increase maintainability as well as general readability. The filter function will return a new array containing only the elements for which the function expression returned a truthy value.

Another great usage example is an array transformation. You might need to modify the value of each element in an array. Instead of modifying your original array you probably want to have a new array with the modified values. This can easily be done using the Array.map extra fun

var names = ['Anton', 'Bob', 'Phil', 'Ana', 'Eve'];
 
console.log(names.map(function(name) {
  return name[0] + '.';
}));
// Will output ["A.", "B.", "P.", "A.", "E."]

Isn’t that pure beauty? We can produce an array containing only the initials of all first names in a very simple and readable code.

As the Array Extra functions all produce a new object and return it, you can also easily chain these functional calls to perform complex transformations.

var names = ['Anton', 'Bob', 'Phil', 'Ana', 'Eve'];
 
var output = names.filter(function(name) {
  return name.length > 3;
}).map(function(name) {
  return name[0] + '.';
});
 
console.log(output);
// Will output ["A.", "P."]

Of course, this adds to the already present closure performance overhead with the fact that if you chain a lot of these functions, you’re actually looping over your data a few times instead of once. But again, let’s think in real volume and decide where the benefit of having nice, slim, and maintainable code outweighs the suffering from performance drawbacks.

I’d like to show you some more small examples of how and where to use Array Extras and functional style JavaScript. The following examples should give you an idea of how you can approach algorithmic or business problems based on data.

console.log([1, 2, 3, 4, 5, 6, 7, 8].reduce(function(previousValue, value) {
    return previousValue + value;
  }, 0));
// Will output 36

Array.reduce easily lets you reduce a list of data to a single value. This comes in handy when you want to sum up data but there are also more advanced and maybe hijacked ways of using Array.reduce.

console.log(['Bob', 'Alice', 'Peter', 'Paul', 'David'].reduce(function(obj, name) {
    obj[name] = name.length;
    return obj;
  }, {}));
// Will output an object {Alice: 5, Bob: 3, David: 5, Paul: 4, Peter: 5}

This example creates an object that contains names as properties with the corresponding name length count as values. Like this you can easily map an array into an object.

The other way around can also be handy. Let’s use Object.keys for this purpose:

var fields = {
  'name': 'Atari T-Shirt',
  'size': 'xl',
  'color': 'white',
  'description': 'A white XL Atari T-Shirt'
};
 
console.log(Object.keys(fields).map(function(fieldKey) {
    return fields[fieldKey];
  }).filter(function(value) {
    return value.match(/x/i);
  }));
// Will output ["xl", "A white XL Atari T-Shirt"]

The above example could be used for a full text search for example. You can see this can be extended to almost any use-case.

Let’s look at some more, probably unconventional applications.

console.log([1.1, 2.6, 3.1, 4.9, 10.0001].map(Math.round));
// Will output [1, 3, 3, 5, 10]

This one-liner magically prints out an array with rounded values! It takes our input array and creates a new mapped array using Math.round as transformation function. As you can see you can also use the built-in functions in the Array Extras. for Array.map you just need to pass functions where the first argument accepts an element of your array and returns the modified element.

console.log(
  ['screen and (min-width: 1024px)', 'screen and (max-width: 320px)', 'print']
  .map(window.matchMedia)
  .map(function(m) { 
    return m.matches;
  }));
// Output depends on your media but likely [true, false, false]

The above code will first map the media query strings to an array that contains a MediaQueryList for the given string and then maps this again to a new array that will contain a boolean if the MediaQueryList matches or not.

var containsE = 'Welcome to this functional style javascript examples!'
  .split(' ')
  .filter(RegExp.prototype.test, /.*e.*/i)
  .reduce(function(previousValue, value) {
    return previousValue + '-' + value;
  });
 
console.log(containsE);
// Will output "Welcome-style-examples!"

This weird-looking example plays with the fact that the Array Extra functions luckily accept always the last parameter where you can specify the this argument in the context of the function call. This enables you to use prototype functions that rely on the this keyword (like RegExp.prototype.test in this example).

Building a lodash like _.times function in functional style is tricky because Array Extras ignore array holes. You can, however, use apply (which does not ignore holes and treats them as undefined) to get around this issue.

The following example will NOT put anything to the console, because creating an array with length initialization will create an empty array (new Array(5) is equal to [,,,,,]).

var arr = new Array(5);
arr.forEach(function(element, index) {
  console.log('Index => ' + index);
});

Using Array.apply to call the array constructor dynamically with a newly created Array using the length constructor will solve our issue and fill the holes with undefined.

var times = function(times) {
  return Array.apply(null, new Array(times));
};
 
times(5).forEach(function(element, index) {
  console.log('Index => ' + index);
});

The above code lets you generate an Array initialized with undefined, that you can use to iterate over. Why you would like to do such a nonsense? I don’t know! But you could for example use it to generate 10 random numbers like so:

var times = function(times) {
  return Array.apply(null, new Array(times));
};
 
console.log(times(10).map(Math.random));

As you can see, there are so many good reasons to adopt a more functional style of writing JavaScript where the most valid reasons are probably a simplification of code, maintainability, and human readability.

I hope you’ve enjoyed the above examples and if you have more please add them in the comments!

Get the latest from Coalist

Share your email so coalist can send you guides and industry news.

    By clicking this button, you agree to our Terms of Service and Privacy Policy.

    Partners

    Swiss Made Software