我不知道你为什么会调用map
一个“关闭”。闭包完全是另一回事。map
是一个高阶函数——定义为对函数进行操作(获取或返回)的函数。这种编程风格可以粗略地称为“函数式”。
使用类似的函数有优点和缺点map
。正如一位评论者指出的那样,它更加紧凑:
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; }
.
更紧凑意味着更具可读性并且更小的 bug 表面积。使用名为add
还增强了可读性;我们很容易直觉到该操作就是将数组的元素相加。
基本上,所有数组函数都有 for 循环等效项,这需要设置更多变量并编写更多逻辑。例如,map
is
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
etc.
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)
仅对位置 1000000 处存在的单个元素进行操作,并根据需要返回一个稀疏数组。
功能性风格还为灵活性提供了额外的可能性。假设我们想要概括乘法的想法。我可以编写一个高阶函数来创建一个将某个值乘以特定因子的函数:
function multiply(n) {
return function(x) {
return n * x;
};
}
现在我可以写了
array.map(multiply(2))
在 for 循环解决方案中很难实现这种程度的简洁性和表现力。
forEach
and map
等可能比 for 循环慢。如果您的代码在紧密循环中运行一百万次,这可能会成为一个问题。在现实世界中,这很少是一个问题。最好优先考虑代码的可读性和紧凑性。
然而,没有人强迫你使用map
or filter
。在 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!!
}