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.
谢谢你的回复。
在你的例子中, map
和forEach
之间的本质区别是forEach
对原始数组元素进行操作,而map
显式地返回一个新的数组。
使用forEach
您正在采取一些措施,并可以更改原始数组中的每个元素。 forEach
方法运行您为每个元素提供的函数,但不返回( undefined
)。 另一方面, map
遍历数组,将一个函数应用于每个元素,并将结果作为新数组发送 。
forEach
的“副作用”是原始数组正在改变。 使用map
“无副作用”意味着,在习惯用法中,原始数组元素不会改变; 新arrays是原始数组中每个元素的一对一映射 – 映射变换是您提供的函数。
没有涉及数据库的事实并不意味着你不必操作数据结构,毕竟这是任何语言编程的本质之一。 至于你的最后一个问题,你的数组不仅可以包含数字,而且可以包含对象,string,函数等。
这两种方法的主要区别在于概念和风格:当你想要对数组中的每个元素做某事时,你可以使用forEach
(“with”是你所引用的“副作用”的意思,我想),而当您想要复制和转换数组的每个元素(而不更改原始)时使用map
。
因为map
和forEach
调用数组中的每个项目的函数,并且该函数是用户定义的,所以几乎没有什么可以用一个而不用另一个。 使用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编程中,大部分时间出现副作用。 你可能正在使用它,而没有意识到。
forEach
和map
之间的重要区别在于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
可以是任意的对象; 这绝不是必然的。
至于是否有map
和forEach
真实用途,以及询问for
或while
循环是否有实际用途。
虽然所有以前的问题都是正确的,但我肯定会做出不同的区分。 map
和forEach
可能意味着意图。
我喜欢使用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完全),但是 – 我们到了那里。 如果我需要在浏览器中运行它,我相信它会很好地传递。