Dan*_*iel 0 javascript closures loops
似乎功能迭代器正在取代JS中for循环的使用。
与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;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我不知道为什么您会称其map为“关闭”。关闭完全是另外一回事。map是一个高阶函数-定义为对一个函数进行操作(获取或返回)的函数。这种编程风格可以宽松地称为“功能性”。
使用诸如之类的功能有优点也有缺点map。正如一位评论者所指出的,它更加紧凑:
function sum(array) {
var sum = 0;
for (var i = 0; i < array.length; i++) sum += array[i];
return sum;
}
Run Code Online (Sandbox Code Playgroud)
与
function sum(array) {
return array.reduce(add);
}
Run Code Online (Sandbox Code Playgroud)
哪里add是function add(a, b) { return a + b; }。
更加紧凑意味着更易于阅读,并且表面积更小。使用命名的函数add还可以增强可读性。我们可以很容易地看出操作是添加数组的元素。
基本上,所有数组函数都有for-loop等效项,它们需要设置更多的变量并编写更多的逻辑。例如,map是
function map(array, fn) {
var result = [];
for (var i = 0; i < array.length; i++) result.push(fn(array[i]));
return result;
}
Run Code Online (Sandbox Code Playgroud)
这可以更紧凑地编写为array.map(fn)。
在很多情况下,我们可能已经定义了执行元素映射或元素过滤的函数。在这种情况下,我们可以简单地按原样使用函数map,reduce等等。
map并且它的朋友也具有对稀疏数组友好的优势。例如:
var a = [];
a[1000000] = 1;
Run Code Online (Sandbox Code Playgroud)
现在我们将每个元素加倍:
function double(array) {
var result = [];
for (var i = 0; i < array.length; i++) result.push(array[i] * 2);
return result;
}
Run Code Online (Sandbox Code Playgroud)
这将循环一百万次并返回一个充满NaN的数组。相反
array.map(elt => elt*2)
Run Code Online (Sandbox Code Playgroud)
仅对位置1000000上存在的单个元素进行运算,并返回一个稀疏数组。
功能风格还为灵活性提供了更多可能性。假设我们要推广乘以事物的想法。我可以编写一个高阶函数来创建一个将某个值乘以特定因子的函数:
function multiply(n) {
return function(x) {
return n * x;
};
}
Run Code Online (Sandbox Code Playgroud)
现在我可以写
array.map(multiply(2))
Run Code Online (Sandbox Code Playgroud)
在for循环解决方案中,很难达到这种简洁和表达的水平。
forEach和map等都是可能比一个for循环慢。如果您的代码在紧密的循环中运行一百万次,则可能会出现问题。在现实世界中,这很少是一个问题。最好优先考虑代码的可读性和紧凑性。
但是,没有人强迫您使用map或filter。在ES7或它将被称为的任何版本中,您将能够使用数组推导以更易读的方式完成同一件事:
[ for (i of array) if (i % 2) i + 1 ]
Run Code Online (Sandbox Code Playgroud)
结合了过滤器和地图。
在更远的地方,如果您打算编写一个在数组上迭代的生成器,并从每个元素产生一些计算,则将需要使用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!!
}
Run Code Online (Sandbox Code Playgroud)