javascript forEach方法有什么用(该映射不能)?

我在map和foreach中看到的唯一区别是map正在返回一个数组, forEach不是。 但是,我甚至不明白forEach方法的最后一行“ func.call(scope, this[i], i, this); ”。 例如,不是“ this ”和“ scope ”是指同一个对象,而不是this[i]i指的是循环中的当前值?

我在另一个post上注意到有人说:“当你想在列表的每个元素的基础上使用forEach ,例如,你可能会添加一些东西到页面,基本上,当你想要”副作用“我不知道副作用是什么意思。

 Array.prototype.map = function(fnc) { var a = new Array(this.length); for (var i = 0; i < this.length; i++) { a[i] = fnc(this[i]); } return a; } Array.prototype.forEach = function(func, scope) { scope = scope || this; for (var i = 0, l = this.length; i < l; i++) { func.call(scope, this[i], i, this); } } 

最后,javascript中是否有这些方法的实际用法(因为我们没有更新数据库),而不是像这样操纵数字:

 alert([1,2,3,4].map(function(x){ return x + 1})); //this is the only example I ever see of map in javascript. 

谢谢你的回复。

在你的例子中, mapforEach之间的本质区别是forEach对原始数组元素进行操作,而map显式地返回一个新的数组。

使用forEach您正在采取一些措施,并可以更改原始数组中的每个元素。 forEach方法运行您为每个元素提供的函数,但不返回( undefined )。 另一方面, map遍历数组,将一个函数应用于每个元素,并将结果作为新数组发送

forEach的“副作用”是原始数组正在改变。 使用map “无副作用”意味着,在习惯用法中,原始数组元素不会改变; 新arrays是原始数组中每个元素的一对一映射 – 映射变换是您提供的函数。

没有涉及数据库的事实并不意味着你不必操作数据结构,毕竟这是任何语言编程的本质之一。 至于你的最后一个问题,你的数组不仅可以包含数字,而且可以包含对象,string,函数等。

这两种方法的主要区别在于概念和风格:当你想要对数组中的每个元素做某事时,你可以使用forEach (“with”是你所引用的“副作用”的意思,我想),而当您想要复制和转换数组的每个元素(而不更改原始)时使用map

因为mapforEach调用数组中的每个项目的函数,并且该函数是用户定义的,所以几乎没有什么可以用一个而不用另一个。 使用map来就地修改数组和/或对数组元素进行操作是可能的,虽然很糟糕。

 var a = [{ val: 1 }, { val: 2 }, { val: 3 }]; a.map(function(el) { el.val++; // modify element in-place alert(el.val); // do something with each element }); // a now contains [{ val: 2 }, { val: 3 }, { val: 4 }] 

但是对于你使用forEach的意图要forEach得多和明显:

 var a = [{ val: 1 }, { val: 2 }, { val: 3 }]; a.forEach(function(el) { el.val++; alert(el.val); }); 

特别是如果像现实世界中的情况一样, el是一个有用的人类可读的variables:

 cats.forEach(function(cat) { cat.meow(); // nicer than cats[x].meow() }); 

以同样的方式,你可以很容易地使用forEach来创build一个新的数组:

 var a = [1,2,3], b = []; a.forEach(function(el) { b.push(el+1); }); // b is now [2,3,4], a is unchanged 

但是使用map更清晰:

 var a = [1,2,3], b = a.map(function(el) { return el+1; }); 

还要注意,因为map创build了一个新的数组,所以当你需要迭代的时候,可能至less会有一些性能/内存命中,特别是对于大型数组 – 参见http://jsperf.com/map-foreach

至于你为什么要使用这些函数,那么在你需要在javascript中进行数组操作的时候,它们是很有用的,即使我们只是在浏览器环境中谈论javascript,你正在访问一个数组,你没有用手写下代码。 您可能正在处理页面上的DOM元素数组,或从AJAX请求中提取的数据或用户在表单中input的数据。 我遇到的一个常见示例是从外部API提取数据,您可能希望使用map将数据转换为所需的格式,然后使用forEach遍历新数组,以便将其显示给用户。

投票答案(来自Ken Redler)是误导性的。

计算机科学的副作用意味着函数/方法的属性改变了全局状态[wiki] 。 从某种狭义的意义上讲,这也可能包括从一个全球性的国家而不是从争论中读取。 在必要的或OO编程中,大部分时间出现副作用。 你可能正在使用它,而没有意识到。

forEachmap之间的重要区别在于map分配内存并存储返回值,而forEach则抛弃它。 有关更多信息,请参阅emca规范 。

至于人们说forEach的原因是什么,当你想要一个副作用是forEach的返回值总是undefined 。 如果没有副作用(不改变全局状态),那么这个函数只是在浪费CPU时间。 优化编译器将消除这个代码块,并用最终值( undefined )replace它。

顺便说一句,应该指出的是,JavaScript对副作用没有限制。 您仍然可以修改map内的原始数组。

 var a = [1,2,3]; //original var b = a.map( function(x,i){a[i] = 2*x; return x+1} ); console.log("modified=%j\nnew array=%j",a,b); // output: // modified=[2,4,6] // new array=[2,3,4] 

这是一个意想不到的答案,一个美丽的问题。

以下是基于Array.prototype.map()的官方描述 。

没有什么 forEach()可以做map()不能。 也就是说, map()forEach()严格超集

尽pipemap()通常用于创build一个新的数组,但可能用于更改当前数组。 以下示例说明了这一点:

 var a = [0, 1, 2, 3, 4], mapped = null; mapped = a.map(function (x) { a[x] = x*x*x; return x*x; }); console.log(mapped); // logs [0, 1, 4, 9, 16] As expected, these are squares. console.log(a); // logs [0, 1, 8, 27, 64] These are cubes of the original array!! 

在上面的例子中, a被方便地设置为使得a[i] === i对于i < a.length 。 即便如此,它也certificate了map()的强大function,尤其是它能够更改所调用的数组。

注1:
官方的描述暗示着map()甚至可以改变被调用的数组的长度 ! 但是,我看不到(一个好的)理由。

笔记2:
虽然map()映射是forEach()一个超集,但仍然应该使用forEach() ,当需要对给定数组进行更改时。 这使你的意图清晰。

希望这有助于。

你可以像使用forEach一样使用map

但是,这将比现在做得更多。

scope可以是任意的对象; 这绝不是必然的。

至于是否有mapforEach真实用途,以及询问forwhile循环是否有实际用途。

虽然所有以前的问题都是正确的,但我肯定会做出不同的区分。 mapforEach可能意味着意图。

我喜欢使用map当我只是以某种方式转换现有的数据(但要确保原始数据不变。

当我修改collections时,我喜欢使用forEach

例如,

 var b = [{ val: 1 }, { val: 2 }, { val: 3 }]; var c = b.map(function(el) { return { val: el.val + 1 }; // modify element in-place }); console.log(b); // [{ val: 1 }, { val: 2 }, { val: 3 }] console.log(c); // [{ val: 3 }, { val: 4 }, { val: 5 }] 

我的经验法则是确保当你map你时,总是创build一个新的对象/值来返回源列表中的每个元素并返回它,而不是仅仅对每个元素执行一些操作。

除非你真的需要修改现有的列表,否则修改它并没有什么意义,并且更好地适应function/不可变的编程风格。

再一次,我觉得自己就像一个死灵巫师,回答了5年前问过的问题(愉快地有最近的活动,所以我不是唯一一个干扰死亡的人)。

其他人已经发布关于你的主要问题关于function之间的区别。 但对于…

有没有这些方法在JavaScript中的任何实际用途(因为我们不更新数据库),而不是像这样操纵数字:

…你应该问这很有趣。 就在今天,我写了一段代码,它使用map来进行转换,从正则expression式将多个值分配给多个variables。 它被用来将一个非常复杂的基于文本的结构转换成可视化的数据…但是为了简单起见,我将提供一个使用datestring的例子,因为这可能对每个人都更为熟悉(不过,如果我的问题实际上是与date,而不是地图我会使用date对象,这将自己的工作出色)。

 const DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/; const TEST_STRING = '2016-01-04T03:20:00.000Z'; var [ iYear, iMonth, iDay, iHour, iMinute, iSecond, iMillisecond ] = DATE_REGEXP // We take our regular expression and... .exec(TEST_STRING) // ...execute it against our string (resulting in an array of matches)... .slice(1) // ...drop the 0th element from those (which is the "full string match")... .map(value => parseInt(value, 10)); // ...and map the rest of the values to integers... // ...which we now have as individual variables at our perusal console.debug('RESULT =>', iYear, iMonth, iDay, iHour, iMinute, iSecond, iMillisecond); 

所以…虽然这仅仅是一个例子 – 只是为了数据做了一个非常基本的转换(仅仅是为了举例),没有map就做了这个工作将是一个非常单调乏味的任务。

当然,它是用JavaScript的版本编写的,我不觉得太多的浏览器支持(至less完全),但是 – 我们到了那里。 如果我需要在浏览器中运行它,我相信它会很好地传递。