The map()
, filter()
, and reduce()
functions are not alone in our toolbox of helper functions. There exist many more functions that can be plugged into nearly any functional application.
Essentially the non-pure version of map()
, forEach()
iterates over an array and applies a callback()
function over each item. However, it doesn't return anything. It's a cleaner way of performing a for
loop.
Syntax: arr.forEach(callback [, thisArg]);
Parameters:
callback()
: This function is to be performed for each value of the array. With these parameters:currentValue
: This parameter gives the current element being processed in the arrayindex
: This parameter gives the index of the current element in the arrayarray
: This parameter gives the array being processedthisArg
: This function is optional. Value is used as this
when executing callback
.Examples:
var arr = [1,2,3]; var nodes = arr.map(function(x) { var elem = document.createElement("div"); elem.textContent = x; return elem; }); // log the value of each item arr.forEach(function(x){console.log(x)}); // append nodes to the DOM nodes.forEach(function(x){document.body.appendChild(x)});
When working with arrays instead of for
and while
loops, often you will need to join multiple arrays together. Another built-in JavaScript function, concat()
, takes care of this for us. The concat()
function returns a new array and leaves the old arrays untouched. It can join as many arrays as you pass to it.
console.log([1, 2, 3].concat(['a','b','c']) // concatenate two arrays); // Output: [1, 2, 3, 'a','b','c']
The original array is untouched. It returns a new array with both arrays concatenated together. This also means that the concat()
function can be chained together.
var arr1 = [1,2,3]; var arr2 = [4,5,6]; var arr3 = [7,8,9]; var x = arr1.concat(arr2, arr3); var y = arr1.concat(arr2).concat(arr3)); var z = arr1.concat(arr2.concat(arr3))); console.log(x); console.log(y); console.log(z);
Variables x
, y
and z
all contain [1,2,3,4,5,6,7,8,9]
.
Another native JavaScript function helps with array transformations. The reverse()
function inverts an array, such that the first element is now the last and the last is now the first.
However, it does not return a new array; instead it mutates the array in place. We can do better. Here's an implementation of a pure method for reversing an array:
var invert = function(arr) { return arr.map(function(x, i, a) { return a[a.length - (i+1)]; }); }; var q = invert([1,2,3,4]); console.log( q );
Much like our map()
, filter()
, and reduce()
methods, the sort()
method takes a callback()
function that defines how the objects within an array should be sorted. But, like the reverse()
function, it mutates the array in place. And that's no bueno.
arr = [200, 12, 56, 7, 344]; console.log(arr.sort(function(a,b){return a–b}) ); // arr is now: [7, 12, 56, 200, 344];
We could write a pure sort()
function that doesn't mutate the array, but sorting algorithms is the source of much grief. Significantly large arrays that need to be sorted really should be organized in data structures that are designed just for that: quickStort, mergeSort, bubbleSort, and so on.
The Array.prototype.every()
and Array.prototype.some()
functions are both pure and high-order functions that are methods of the Array
object and are used to test the elements of an array against a callback()
function that must return a Boolean representing the respective input. The every()
function returns True
if the callback()
function returns True
for every element in the array, and the some()
function returns True
if some elements in the array are True
.
Example:
function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } console.log([1, 2, 3, 4].every(isNumber)); // Return: true console.log([1, 2, 'a'].every(isNumber)); // Return: false console.log([1, 2, 'a'].some(isNumber)); // Return: true