Monday, December 11, 2023
119
rated 0 times [  126] [ 7]  / answers: 1 / hits: 5426  / 8 Years ago, mon, december 21, 2015, 12:00:00

It seems that functional iterators are replacing the use of for loops in JS.

What is the advantage of passing a function such as `map` or `reduce` compared to a for/while loop?

``````var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});

var doubles = [];
for (i = 0; i < numbers.length; i++) {
doubles[i] = numbers[i] * 2;
}
``````

More From » loops

8

I have no idea why you would call the use of `map` a closure. Closures are something else entirely. `map` is a higher-order function--defined as a function which operates on (takes or returns) a function. This style of programming can loosely be called functional.

There are advantages and disadvantages to using functions like `map`. As one commenter pointed out, it's more compact:

``````function sum(array) {
var sum = 0;
for (var i = 0; i < array.length; i++) sum += array[i];
return sum;
}
``````

vs.

``````function sum(array) {
}
``````

Where `add` is `function add(a, b) { return a + b; }`.

More compact means more readable and less surface area for bugs. The use of the function named `add` also enhances readability; we can easily intuit that the operation is to add the elements of the array.

Basically, all the array functions have for-loop equivalents which require setting up more variables and writing more logic. For instance, `map` is

``````function map(array, fn) {
var result = [];
for (var i = 0; i < array.length; i++) result.push(fn(array[i]));
return result;
}
``````

This can be written (much) more compactly as `array.map(fn)`.

In many cases, we might already have functions defined which do the element mapping, or element filtering we want to do. In that case, we can simply use the functions as is with `map`, `reduce` etc.

`map` and its friends also have the advantage that they are friendly to sparse arrays. For instance:

``````var a = [];
a = 1;
``````

Now we double each element:

``````function double(array) {
var result = [];
for (var i = 0; i < array.length; i++) result.push(array[i] * 2);
return result;
}
``````

This loops one million times and returns an array filled with NaNs. In contrast

``````array.map(elt => elt*2)
``````

operates only on the single element which is present at position 1000000 and returns a sparse array as one would like.

The functional style also opens up additional possibilities for flexibility. Let's say we want to generalize the idea of multiplying things. I can write a higher-order function to create a function which multiplies some value by a particular factor:

``````function multiply(n) {
return function(x) {
return n * x;
};
}
``````

Now I can write

``````array.map(multiply(2))
``````

This level of conciseness and expressiveness is going to be hard to achieve in a for-loop solution.

`forEach` and `map` etc. are likely to be slower than a for loop. This could be an issue if your code is running a million times in a tight loop. In the real world, it rarely is an issue. It is better to prioritize code readability and compactness.

However, no one is forcing you to use `map` or `filter`. In ES7 or whatever it will be called, you will be able to use array comprehensions to accomplish the same thing in even more readable fashion:

``````[ for (i of array) if (i % 2) i + 1 ]
``````

which combines a filter and a map.

A bit further afield, if you are planning to write a generator which iterates over an array, and yield some calculation from each element, you are going to need to use a for loop, since there is no way to yield from within a `forEach` callback:

``````function *double(array) {
for (var i = 0; i < array.length; i++) yield array[i]*2;
}

function *double(array) {
array.forEach(elt => yield elt*2); // DOESN'T WORK!!
}
`````` 