使用函数over循环的优点是什么? [英] What is the advantage of using a function over loops?

查看:152
本文介绍了使用函数over循环的优点是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看起来闭包取代了JS中循环的使用。



与a / while相比,传递map或reduce等函数的优点是什么循环?

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


解决方案

我不知道为什么会调用 map 使用closure。关闭是别的东西。 map 是一个高阶函数 - 定义为对(接受或返回)函数进行操作的函数。



使用 map 这样的函数有优点和缺点。 。正如一个评论者指出的,它更紧凑:

  function sum(array){
var sum = 0;
for(var i = 0; i return sum;
}

vs。

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

其中 add function add(a,b){return a + b; }



更紧凑意味着更多的可读性和更少的表面积的错误。使用名为 add 的函数也增强了可读性;我们可以很容易地直观的操作是添加数组的元素。



基本上,所有的数组函数都有for循环等价,需要设置更多的变量和写更多逻辑。例如, map

  function map(array,fn){ 
var result = [];
for(var i = 0; i return result;
}



这可以写得更紧凑,因为



在许多情况下,我们可能已经定义了函数,这些函数执行元素映射或者我们想要的元素过滤去做。在这种情况下,我们可以直接使用 map reduce 等函数。



map 和它的朋友也有它们对稀疏数组友好的优点。例如:

  var a = []; 
a [1000000] = 1;

现在我们将每个元素加倍:

  function double(array){
var result = [];
for(var i = 0; i return result;
}

这循环100万次并返回一个用NaNs填充的数组。对比

  array.map(elt => elt * 2)
/ pre>

只对存在于位置1000000的单个元素操作,并返回一个稀疏数组。



功能风格也为灵活性带来了额外的可能性。让我们假设我们想把事物乘法的概念推广一下。我可以写一个高阶函数来创建一个函数,它将一些值乘以一个特定的因子:

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

现在我可以写

  array.map(multiply(2))



forEach 并且在for循环解决方案中难以实现这种简洁性和表达性。 map 等可能比一个for循环慢。这可能是一个问题,如果你的代码在一个严格的循环中运行一百万次。在现实世界中,它很少是一个问题。



然而,没有人强迫你使用 map filter 。在ES7或者它将被调用的任何东西,你将能够使用数组的理解以更可读的方式完成同样的事情:

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

一个过滤器和一个映射。



如果你打算写一个生成器遍历数组,并从每个元素产生一些计算,需要使用for循环,因为没有办法从 forEach 回调中产生:

  function * double(array){
for(var i = 0; i }

function * double(array){
array.forEach(elt => yield elt * 2); //不工作!
}


It seems that closures are replacing the use of 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;
}

解决方案

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) {
  return array.reduce(add);
}

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[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 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!!
}

这篇关于使用函数over循环的优点是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆