有个朋友(无中生有)问我,面试官问他,for和forEach有什么区别?
朋友巴拉巴拉的说了一堆,
- 什么一个是原生的,一个是优化的;
- forEach比for优雅;
- forEach支持callback函数;
我的天啊,你是真的不知道说什么了是吗?
那么最主要的区别是什么呢?
- forEach不可以使用return/break中断循环,for可以;
如何在forEach中跳出循环呢?
- forEach使用try/catch可以跳出forEach循环;
那么对于for/forEach/map,我们应该掌握(聊聊)什么呢?
1.简单测下性能区分
// 计算upVotes的和
const posts = [
{id: 1, upVotes: 2},
{id: 2, upVotes: 18},
{id: 3, upVotes: 1},
{id: 4, upVotes: 30},
{id: 5, upVotes: 50}
];
let sum = 0;
console.time('reduce');
sum = posts.reduce((s, p)=> s+=p.upVotes,0);
console.timeEnd('reduce')
sum = 0;
console.time('for 循环');
for(let i=0; i<posts.length; i++) {
sum += posts[i].upVotes;
}
console.timeEnd('for 循环');
sum = 0;
console.time('for each');
posts.forEach(element => {
sum += element.upVotes;
});
console.timeEnd('for each');
sum = 0;
console.time('for of');
for (let item of posts){
sum += item.upVotes;
}
console.timeEnd('for of');
sum = 0;
console.time('map');
posts.map(item=>{
sum += item.upVotes;
})
console.timeEnd('map');
//结果:
// reduce: 0.059ms
// for 循环: 0.003ms
// for each: 0.014ms
// for of: 0.018ms
// map: 0.012ms
由上述小例子看到:性能等级为:for>map>for each>for of>reduce
但在使用途中,按需使用方法即可
如果你需要将数组按照某种规则映射为另一个数组,就应该用 map。
如果你需要进行简单的遍历,用 forEach 或者 for of。
如果你需要对迭代器进行遍历,用 for of。
如果你需要过滤出符合条件的项,用 filter。
如果你需要先按照规则映射为新数组,再根据条件过滤,那就用一个 map 加一个 filter。
不要担心这样会慢,小数据量服务器根本不在意。
如果你真的需要考虑性能,或者有 break 的需求,就用 for 吧。
1. for
循环代码块一定的次数,for循环可以设置i的开始数字,可以从任何一个位置开始循环。
2. forEach
forEach是一个迭代器,负责遍历可迭代对象。那么遍历,迭代,可迭代对象分别是什么呢。
遍历:指的对数据结构的每一个成员进行有规律的且为一次访问的行为。
迭代:迭代是递归的一种特殊形式,是迭代器提供的一种方法,默认情况下是按照一定顺序逐个访问数据结构成员。迭代也是一种遍历行为。
可迭代对象:ES6中引入了 iterable 类型,ArraySetMapStringargumentsNodeList 都属于 iterable,他们特点就是都拥有 [Symbol.iterator] 方法,包含他的对象被认为是可迭代的 iterable。
forEach的优点:
- forEach方法用来调用数组的每个元素,将元素传给回调函数。
- forEach对于空数组是不会调用回调函数的,即没有返回值。
forEach与for的区别
- forEach不可以使用return/break中断循环
- 使用try/catch可以跳出forEach循环
别再傻乎乎的说什么优点了,面试官就想知道你是否了解,forEach不能使用return/breack中断,以及,如何跳出forEach循环?
try {
let arr = [1, 2, 3, 4];
arr.forEach(function (item, index) {
//跳出条件
if (item === 3) {
throw new Error("LoopTerminates");
}
});
} catch (e) {
if (e.message !== "LoopTerminates") throw e;
}
3.map
map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值。 map方法不会对空数组进行检测,若arr为空数组,则map方法返回的也是一个空数组,map方法不会改变原始数组。 map 最慢的原因是因为 map 会返回一个新的数组,数组的创建和赋值会导致分配内存空间,因此会带来较大的性能开销。如果将map嵌套在一个循环中,便会带来更多不必要的内存消耗。当大家使用迭代器遍历一个数组时,如果不需要返回一个新数组却使用 map 是违背设计初衷的
4. for in
遍历数组或者对象的属性(对数组或者对象的属性进行循环操作) for/in 循环会访问该对象的原型,应该用在非数组对象的遍历上,不建议使用该方法遍历数组。
for in与for的区别 数组既可以用for循环,也可以用for in循环(区别:for循环可以设置i的开始数字,可以从任何一个位置开始循环,但是for in循环不能设置,只能从第一个到最后一个进行循环)。 json只能用for in循环,因为json的下标是没有规律的字符串,没有length。
寄语
抓住重点
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情