最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What is the advantage of using a function over loops? - Stack Overflow

programmeradmin4浏览0评论

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 pared 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;
}

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 pared 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;
}
Share Improve this question edited Apr 22, 2019 at 3:15 user6269864 asked Dec 21, 2015 at 18:35 DanielDaniel 35.7k17 gold badges114 silver badges161 bronze badges 4
  • 4 Uhm, it's not the closure, it's what the methods do? map and reduce do specific things to arrays, they don't just iterate like a for loop ? – adeneo Commented Dec 21, 2015 at 18:36
  • 1 Conciseness (that gets better with arrow funcs from es6) – raina77ow Commented Dec 21, 2015 at 18:37
  • And if you don't like them, you don't have to use them, most things can be done without the new(ish) Array methods. – adeneo Commented Dec 21, 2015 at 18:38
  • 1 the closure formed by the anonymous callback passed to .map() here has basically nothing to do with how any of the code works. The function itself does of course, but not the closures formed by the invocations. – Pointy Commented Dec 21, 2015 at 18:38
Add a ment  | 

3 Answers 3

Reset to default 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 menter pointed out, it's more pact:

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

vs.

function sum(array) {
  return array.reduce(add);
}

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

More pact 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 pactly 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[1000000] = 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 pactness.

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 prehensions to acplish the same thing in even more readable fashion:

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

which bines 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!!
}

It's a paradigm shift. The latter is a form of imperative programming, where the user is the one creating data that the puter consumes. The former is essentially a more functional based approach stemming from mathematics, utilizing data (code) that already exists.

There is no theoretical (processing) advantage of one over the other, though applied to the current state of puters, functional programming bees more useful as processing power bees greater.

Functional programming allows a form of reasoning based in mathematics emphasizing inputs and outputs. JavaScript in particular is good at handling this style due to functions being first-class data types

good answers here already. will just add one thing i came to appreciate with time: when you do things the "imperative"/old way it tends to encourage a style of programming with a lot of intermediate variables, mutable things all over and also the "while i'm iterating i might as well do this other thing on the same data" which is the biggest trap in code design - sacrificing separation of concerns for dubious performance gains. Consider this example

const numbers = [1,4,9,16];
let sum = 0;
let onlyEvenNumbers = [];
for(i = 0; i < numbers.length; i++) {
  sum += numbers[i];
  if(numbers[i] % 2 == 0) {
    onlyEvenNumbers.push(numbers[i]);
  }
}

this is bad imo cause you're gaining very little (if any) performance and the for loop doesn't have a clear single purpose. of course in this simple case it's probably ok, but it can get real ugly real fast. also it's not clear at first glance what gets stored in the onlyEvenNumbers var until you read to the bottom of the for loop - again, probably ok here, but if the for loop gets big it may get confusing. functional approach for the win (also notice things can be not only const, but are even not mutated once constructed):

const numbers = [1,4,9,16];
const sum = numbers.reduce((acc, val) => acc + val);
const onlyEvenNumbers = numbers.filter(num => num % 2 == 0);
发布评论

评论列表(0)

  1. 暂无评论