2015-12-21 25 views
-2

似乎闭包正在取代JS中循环的使用。在循环中使用函数的优点是什么?

与for/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; 
} 
+4

呃,这不是关闭,这是什么方法呢? 'map'和'reduce'对数组做了特定的事情,它们不仅仅像'for'循环那样迭代? – adeneo

+1

简洁性(使用es6中的箭头funcs会更好) – raina77ow

+0

如果您不喜欢它们,则不必使用它们,但大多数情况下都可以在不使用新的(ish)数组方法的情况下完成。 – adeneo

回答

3

我不知道为什么你会打电话给使用map的“闭包”。闭包完全是另一回事。 map是一个高阶函数 - 定义为一个函数,它对(函数或函数)进行操作。这种编程风格可以松散地称为“功能性”。

使用map等功能有其优点和缺点。正如一位评论者指出的那样,这是更紧凑:

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

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

哪里addfunction add(a, b) { return a + b; }

更紧凑意味着更易读和更少的表面区域的bug。使用名为add的功能也增强了可读性;我们可以很容易地认为操作是添加数组的元素。

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

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

这可以写成(多)更简洁的array.map(fn)

在很多情况下,我们可能已经定义了函数来进行元素映射或者我们想要做的元素过滤。在这种情况下,我们可以简单地使用map,reduce等的功能。

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

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

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

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

这个循环一百万次,并返回充满NaN的数组。相比之下

array.map(elt => elt*2) 

仅是存在于百万位置,并返回一个稀疏阵列作为一个希望单个元件上进行操作。

功能风格也为灵活性打开了额外的可能性。假设我们想概括一下乘法事物的概念。我可以写一个高阶函数来创建它通过特定的因素乘以某个值的函数:

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

现在我可以写

array.map(multiply(2)) 

简洁和表现的这种水平将是硬在for-loop解决方案中实现。

forEach and map等可能比for循环慢。如果您的代码在紧密循环中运行一百万次,这可能是一个问题。在现实世界中,它很少是一个问题。优先考虑代码可读性和紧凑性。

但是,没有人强迫您使用mapfilter。在ES7或不管它会叫,你将能够使用数组解析来实现在更可读的方式同样的事情:

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

它结合了过滤器和地图。

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

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

这是一个范式转变。后者是一种命令性编程形式,其中用户是创建计算机消耗的数据的人。前者基本上是一种更加基于功能的方法,源于数学,利用已经存在的数据(代码)。

虽然应用于计算机的当前状态,但理论(处理)优势并不存在,但随着处理能力的增强,功能编程变得更加有用。

函数式编程允许基于数学的推理形式强调输入和输出。由于功能是一流的数据类型,JavaScript特别擅长处理这种风格。

相关问题