这是我不明白的事情。几天前我刚刚学到的map
函数应该是一些令人惊奇的函数,它会改变我编写代码的方式,如果我找到它的用途。但我仍然没有看到它与forEach
有什么不同。唯一的区别是传递给map
的函数用return
值替换当前元素。但forEach
也可以这样做,这意味着map
只是forEach
的不太通用的版本。
MDN上的示例:
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots is now [1, 2, 3], numbers is still [1, 4, 9]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
好的,很酷,我猜?
我可以使用forEach
执行此操作:
var numbers = [1, 4, 9];
var roots = numbers.forEach(function(el){el=Math.sqrt(el);});
// roots is now [1, 2, 3], numbers is still [1, 4, 9]
其他例子:
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.map(function(obj){
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray is now [{1:10}, {2:20}, {3:30}],
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
我可以用forEach
做到这一点,它看起来几乎相同。
map
有什么好处?在forEach
不起作用的情况下,它的工作原理是什么?
答案 0 :(得分:4)
区别在于forEach
“遍历数组”而map
“遍历数组并返回结果”
var numbers = [1, 4, 9];
var roots = numbers.forEach(Math.sqrt);
// roots is undefined, numbers is still [1, 4, 9]
var roots = numbers.map(Math.sqrt);
// roots is [1, 2, 3], numbers is still [1, 4, 9]
map
有什么好处?它使您的代码保持小巧和智能,因为您不需要为内置函数定义匿名函数。
var numbers = [1, 4, 9];
var roots = [];
numbers.forEach(function(val){ roots.push( Math.sqrt(val) ); });
// roots is now [1, 2, 3], numbers is still [1, 4, 9]
在现有示例中证明了返回结果的值(没有双关语意图)......
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.map(function(obj){ // <---------------- map
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray is now [{1:10}, {2:20}, {3:30}],
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];
var reformattedArray = kvArray.forEach(function(obj){ // <---------------- forEach
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray is now undefined,
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
答案 1 :(得分:2)
<强>地图
map
遍历列表并返回一个新列表,而不更改任何其他内容。它不会改变原始列表。它没有副作用。使用map
,您可以使用与基元一起使用的常规函数并提升此函数,以便它可以使用这些基元的列表:
const map = (f, xs) => xs.map(x => f(x));
const sqr = x => x * x;
let xs = [1,2,3];
let x = 3;
sqr(x); // 9
sqr(xs); // Error
let ys = map(sqr, xs); // [1,4,9]
xs; // [1,2,3]
该示例说明map
如何在sqr
的上下文中提升xs
,以便它可以对xs
的元素进行平方。通过这种方式,您可以重用数组的常规函数。
<强>的forEach 强>
forEach
没有结果值。没有任何结果值的函数是没用的,除非它有一些副作用。因此forEach
必须对它迭代的元素应用副作用,以便做一些有意义的事情:
let ys = xs.forEach(sqr); // undefined
xs; // [1,2,3]
// without side effects, nothing has happened
const sqrWithSideEffect = (x, idx, arr) => arr[idx] = x * x; // ugly, isn't it?
xs.forEach(sqrWithSideEffect); //
xs; // [1,4,9]; // side effect: destructive update of xs
结论:forEach
来自函数式编程的命令式map
。两者都代表了对立的范式。因此,如果您真的想了解两个函数之间差异的后果,您必须了解两个编程范例之间的差异。