5 Minute JavaScript #19: Polyfills

The past few weeks were dedicated to the useful array methods. However these methods have been implemented in ECMAScript 5 and are therefore not available in older browsers such as IE8 and sometimes we have to support legacy browsers.

In JavaScript, we use polyfills to create behavior that is not implemented in browser. We can use polyfills to add every kind of behaviour to our application and a lot of websites provide these polyfills.

Basically what happens is that we first do a feature detection. Is the feature available in the browser? For example, does Array.prototype.map exist? Yes? That’s great! It means the feature has been implemented and is probably faster than every polyfill that we could come up with. Is it not available? Too bad, but we can create the Array.prototype.map method ourselves.

The Mozilla Developer Network has some of the most robust polyfills that are still fast in use. It also has an excellent documentation about the array methods. Here’s the page for the map functionality.

Using a polyfill doesn’t change the way the method is being called. If your browser does not support the map-method and you use a polyfill, you will still use it like this: [1, 2, 3].map(…); This is useful, because you don’t have to change syntax for different browsers.

Another solution is to use a framework that has implemented these functionalities. One of my favourites is underscore. This framework adds more useful methods than just the array methods to your function toolbelt.

framework adds more useful methods than just the array methods to your function toolbelt.

5 Minute JavaScript #18: reduce

The past weeks we dived in the wonderful world of array methods. Previously we already discussed forEach, filter, some and every, and map. Today we’ll take a look at the reduce method. While being extremely useful, its concept can be hard to grasp.

Also known as fold (in this case foldLeft) in other functional programming languages, reduce kan be used to combine all elements of an array into one single return value. That return value can be anything. It could be an array (then the reduce functions as a filter/map), but it can also be: an object, string, number, boolean… Everything is possible.

A simple example can be to use the reduce method for calculating a sum. Here’s the code how we would write it in any other imperative language.

var numbers = [1, 2, 3];
var sum = 0;
for (var i = 0; i < numbers.length; i++) {
	sum += numbers[i];
}

We can rewrite this code as follows using the reduce method

var sum = numbers.reduce(function (prev, cur) { return prev + cur; });

The reduce callback function takes two important parameters (prev, cur in this case). First of all we have the previous value. This is the value that got returned in the previous callback function. The current parameter is the current item in the list.

You might get your head around this functionality, but it’s not really useful in real applications. Its real strength lies in the fact that you can press a lot of elements together into one single return value. A use case for reduce might be this:

var user = { id: 'UUID', version: 0 };
var users = [/* list of users */];
var idVersionMap = users.reduce(function (map, user){ 
    map[user.id] = user.version; 
    return map; 
}, {});

In our blogpost about the map method we used map to create a new list of objects (with id and version). Here, we use the reduce method to create a single object that acts as a map with key = id and value = version. The empty {} that we passed along in the reduce callback function is the initial value the method needs to use.

5 Minute JavaScript #17: some and every

In the previous blogpost we discussed the map method on arrays in JavaScript. We still have some useful methods the go. Next in line are the some and every methods. These methods are similar and can be very useful when validating data.

var isEven = function (n) { return n % 2 === 0 };
var areAllEven = [2, 4, 6].every(isEven);
var someEven = [1, 2, 3].some(isEven);

The every method will check if for every element in the list, the callback functions returns true. If there is one single item in the array that returns false, the every method will return false as well. The some method is satisfied when there is at least one element in the array where the callback returns true.

var stockItem = { hasBeenShipped: true };
var selection = [/* list of stock items selected in a list */];
var hasNotBeenShipped = function (si) { return !si.hasBeenShipped };
var hasBeenShipped = function (si) { return si.hasBeenShipped };

$('#sendStockItems').attr('disabled', selection.every(hasNotBeenShipped));
$('#sendStockItems').attr('disabled', selection.some(hasBeenShipped));

The example here will disable a button when the selection in the list contains one or more items that already have been shipped. This code is very readable and concise. You can almost read exactly what it does: set attribute disabled when selection has some items that hasBeenShipped.

5 Minute JavaScript #16: map

Last week we took a look at the filter functionality. This week I will show you one of my favourite array methods called: “map”. It’s extremely powerful and useful in so many ways. The purpose of map is simple, it transforms an item in an array and pushes that transformation into a new array. The method then returns that newly created array with all the transformed items. A simple example will show you what it does.

var square = function (item) { return item * item; };
var squares = [1, 2, 3, 4].map(square);

In this example we just square a number in the array. The result will be a new array but with the squared items.

This example is easy to understand, but you might wonder what the practical use is for this function. Well in a lot of applications I find myself using map to select the identifier from an object and pass along a map of id’s.

var user = { id: 'UUID', version: 0, name: 'User 1' };
var users = [/* a list of users */];
var ids = users.map(function (u) {return u.id;}); 
var versions = users.map(function (u) {return u.version});
var idsAndVersions = users.map(function (u) { 
    return { 
        id: u.id, 
        version: u.version 
    };
});

These lists can be used in frameworks, api’s, ajax requests, caching, etc… everywhere you don’t need to know / send the full information of the user.

5 Minute JavaScript #15: filter

In the previous blogpost we discussed the forEach method that iterates over every array. We can now create a filtered array by using this function.

var filtered = []
arr.forEach(function (item) { if (item.isOkay) filtered.push(item); });

While this will work fine, we still need to predefine our filtered array and push it in this array ourselves. We don’t need to… we could just use the filter method on the array prototype.

var filtered = arr.filter(function (item) { return item.isOkay; });

This code isn’t only more readable and a little shorter, it also allows you to chain these methods. Also, you can use abstract validation functions to reuse the filtering.

var isEven = function (number) { return number % 2 === 0; };
var filtered = [1, 2, 3].filter(isEven);

A more practical example:

var stockItem = { category: "toys" /*, and other properties */ };
var stockItems = [/* has a bunch of stockitems with different categories */];

var product = { category: "toys", stockItems: [] };
var products = [/* has a bunch of products */];

var belongsToToyCategory = function (item) { return item.category === "toys";  };

var filteredStockItems = stockItems.filter(belongsToToyCategory);
var filteredProducts = products.filter(belongsToToyCategory);

5 Minute JavaScript #14: forEach

After discussing how to create a range in the last post, we will discuss some of the array methods and how to use them to make your code more readable and concise.

First of all, I want to add that every array method uses the callback pattern. We’ll do a post on this pattern later, when discussing Asynchronous JavaScript, but for now you need to know that callbacks in these functions are called for every item in the array.

The easiest array method is called forEach and will just iterate over every item in the array.

	[1, 2, 3].forEach(function (item) { console.log(item); });

Most people will recognize this method. It iterates over every item and does nothing with the return value you provide. What most programmers don’t know is that you have some additional features in forEach.

	[1, 2, 3].forEach(function (item, index, array) { this.log(item);  }, console);

The forEach function lets you set the functions context (= this, more later) as well. In the previous example I injected console as the ‘this’ value in callback function.

But beware:

	function hasNumber (arr, number) {
		arr.forEach(function (item) { 
			if (item === number) return true; 
		});
	}

While this code might look okay, you must know that JavaScript’s forEach is still a callback function. Returning the value true inside the callback won’t result in the global function (hasNumber) to return true. You should refactor this code to

	function hasNumber (arr, number) {
		var found = false;
		arr.forEach(function (item){ if (item === number) found = true; });
		return found;
	}

By using the some-method you will get an even easier result, but more about that in a future post.

5 Minute JavaScript #13: How to create an array from a range

Previous blogpost we discussed extending native data types in JavaScript. Today we’ll create a method in the array prototype that you can use to easily create a range such as an array.

Some programming languages allow you to easily create an array from a range, such as:

Scala

	val list = 0 until 10 toList

or Ruby

	arr = [0..10]

In JavaScript however, you need to use a for-loop to fill an array with ranged values. You could create a function that returns a filled array based on a from and to value like this:

function fill (from, to) {
 var a = [];
 for (var i = from; i <= to; i += 1) {
   a.push(i);
 }
 return a;
}

But then you have declared a function fill globally; that doesn’t really say much… it would be syntactically more interesting to use the Array prototype like this:

Array.prototype.fill = function (from, to) {
 var a = [];
 for (var i = from; i <= to; i += 1) {
   a.push(i);
 }
 return a;
};

Now we can create a new array using a very simple syntax

	var arr = [].fill(1,5); // results in [1,2,3,4,5]

While not perfect, defining the fill function this way, is a lot more readable. You start with an empty array and you fill it with a range of values. This makes perfect sense.