ECMAScript 5: Array methods

This is the third and final part of my series on ECMAScript 5. In part one, we looked at new methods for object creation and property definition. Part two focused on tamper proofing objects. I'll now provide a quick overview of the new high level array methods.

Unlike the new methods discussed in the first two parts, the methods here are all reproducible using JavaScript itself. Native implementations are simply faster and more convenient. Having a uniform API for these operations also promotes their usage, making code clearer when shared between developers.

Search methods

Array.prototype.indexOf

indexOf provides an easy way to determine whether or not an object is in an array. It returns the first index at which the item was found, or -1 if it was not found at all. Strict equality is used to determine that an item is present in the array. An optional second argument can start the search at an index other than 0.

var arr = ["apple", "banana", "carrot", "apple"];

arr.indexOf("apple"); // 0
arr.indexOf("daikon"); // -1

Array.prototype.lastIndexOf

Identical to indexOf, but returns the last index at which an item is found, if at all.

var arr = ["apple", "banana", "carrot", "apple"];

arr.lastIndexOf("apple"); // 3

Iteration methods

Array.prototype.forEach

Ever seen this before?

for (var i = 0, l = arr.length; i < l; i++) {
  doSomething(arr[i], i, arr);
}

There is now a clean, high level way to do this with forEach. The method accepts a callback which will be executed once for each item in the array. The callback receives three arguments: the value of the current iteration, the index of the current iteration, and the array itself. The following is equivalent to the above:

arr.forEach(doSomething);

An optional second argument specifies the value of this within the callback.

Array.prototype.every

every checks every element in an array against a condition, by means of a passed in function. If any of the items in the array cause the function to return a falsy value, every returns false. If they all return truthy values, every returns true. Like forEach, an optional second argument supplies a value for the callback's this, and the callback itself will receive the same three arguments.

var arr = ["apple", "banana", "carrot", "apple"];

arr.every(function (value, index, array) { return value.length > 1; }); // true
arr.every(function (value, index, array) { return value.length < 6; }); // false

Array.prototype.some

some is similar to every, but the passing condition is that at least one callback returns true, rather than all of them.

var arr = ["apple", "banana", "carrot", "apple"];

arr.some(function (value, index, array) { return value.length < 6; }); // true

Transformation methods

Array.prototype.map

Mapping is the most common transformation. It loops through an array, running a function and creating a new array built from the return values of each iteration. map takes the same optional second argument and receives the same callback arguments as the iteration methods.

var names = ["Abigail", "Bongo", "Carlitos"];

names.map(function (value, index, array) {
  return value + " Jones";
});
// ["Abigal Jones", "Bongo Jones", "Carlitos Jones"]

Array.prototype.filter

Filtering is like mapping, but creates a new array containing only the items of the original array that return a truthy value from the callback. filter takes the familiar optional argument and its callback receives the usual suspects.

var names = ["Abigail", "Bongo", "Carlitos"];

names.filter(function (value, index, array) {
  return value.length > 5
});
// ["Abigail", "Carlitos"]

Array.prototype.reduce

reduce is used to melt the items in an array down to a single value by the operations performed in its callback function. The callback takes the usual three iteration arguments, but is prepended with an extra argument, the value of the previous iteration's result. By default, the first iteration is effectively a no-op, so the calculation begins with the array's first value as the accumulated result and the array's second value as the current iteration. This is probably best illustrated with an example:

[10, 20, 30, 40, 50].reduce(function (accum, value, index, array) {
  return accum + value;
});
// 150

On the first iteration, accum is 10 and value is 20. The return value of accum + value becomes accum on the next iteration of the loop.

reduce can also take an initial value for accum as a second argument. When invoked this way, the first value in the callback is the first item in the array:

[10, 20, 30, 40, 50].reduce(function (accum, value, index, array) {
  return accum + value;
}, 50);
// 200

Array.prototype.reduceRight

reduce's sibling, which performs the same behavior and accepts the same arguments, except it iterates beginning with the rightmost item in the array and moves left. If not specified with a argument, the initial value of accum is the last value in the array, and the initial iteration value is the second to last.

[10, 20, 30, 40, 50].reduceRight(function (accum, value, index, array) {
  return accum - value;
});
// -50

ECMAScript 5 is full of goodness

ECMAScript 5 packs lots of new, useful features into JavaScript which speed up both development and performance of code. The new APIs are implented in the most recent versions of Chrome, Firefox, Safari, and (gasp!) Internet Explorer, so I encourage you to start using these new APIs today!