您的当前位置:首页正文

经典面试题—讲讲forEach、map和for循环的异同点

2024-11-30 来源:个人技术集锦

forEach

没有返回值


var a = [1,2,3,4,5]
var b = a.forEach((item) => {
    item = item * 2
})
console.log(b) // undefined

无法中断执行

forEach 遍历过程中无法中断执行,如果希望符合某种条件时,就中断遍历,要使用for循环

var arr = [1, 2, 3];

for (var i = 0; i < arr.length; i++) {
  if (arr[i] === 2) break;
  console.log(arr[i]);
}

跳过空位

forEach()方法也会跳过数组的空位。

var a = [null, , undefined]
for (let i = 0; i < a.length; i++) {
    console.log('a', a[i]) // null undefined undefined
}
a.forEach(item => {
    console.log('item', item) // null undefined
});

上面代码中,forEach()方法不会跳过undefinednull,但会跳过空位。而for循环不会跳过空位,会认为是undefined

改变数组情况

下面来看几个例子:

var a = [1,2,3,4,5]
a.forEach((item) => {
    item = item * 2
})
console.log(a) // [1,2,3,4,5]

这里原数组并没有发生改变。

var a = [1,'1',{num:1},true] 
a.forEach((item, index, arr) => {
    item = 2 
}) 
console.log(a) // [1,'1',{num:1},true]

这里修改item的值,依然没有修改原数组。

var a = [1,'1',{num:1},true] 
a.forEach((item, index, arr) => { 
    item.num = 2 
    item = 2
}) 
console.log(a)  // [1,'1',{num:2},true]

当修改数组中对象的某个属性时,发现属性改变了。其他值依旧没有改变。

为什么会这样呢?

这里就要引入(stack)内存和(heap)内存的概念了,对于JS中的基本数据类型,如String,Number,Boolean,Undefined,Null是存在于栈内存中的,在栈内存中储存变量名及相应的值。而Object,Array,Function存在于堆内存中,在堆内存中储存变量名及引用位置。

var a = [1,2,3,4,5] 
a.forEach((item, index, arr) => { 
    arr[index] = item * 2 
}) 
console.log(a)  // [2,4,6,8,10]

在回调函数里改变arr的值,原数组改变了。

var a = [1,2,3,4,5] 
a.forEach((item, index, arr) => { 
    arr = 2
}) 
console.log(a)  // [1,2,3,4,5]

map

有返回值

返回一个经过处理后的新数组,但不改变原数组的值。

var a = [1,2,3,4,5]
var b = a.map((item) => {
    return item = item * 2
})
console.log(a)  // [1,2,3,4,5]
console.log(b)  // [2,4,6,8,10]

无法中断执行

同forEach,无法中断执行

跳过空位

同forEach,会跳过空位

改变数组情况

map中可改变原数组的情况和原理与forEach相同

注意事项

虽然map和forEach不能像for循环那样采用break跳出整个循环,但可以曲线救国,采用try...catch并搭配throw error的方式来跳出整个循环(强制退出,非必要不建议)。

以foreach 循环为例:

var arr = [1,2,3]
var newArr = []
arr.forEach((item,index)=>{
    try{
        if(index > 1) {
            throw new Error('文本小于2')
        }
        newArr.push(item)
    }catch (e){
        // throw e
    }
})
console.log(newArr) [1,2]

性能对比

  • for 循环当然是最简单的,因为它没有任何额外的函数调用栈和上下文;

  • forEach 其次,因为它其实比我们想象得要复杂一些,实际上是array.forEach(function(currentValue, index, arr), thisValue)它不是普通的 for 循环的语法糖,还有诸多参数和上下文需要在执行的时候考虑进来,这里可能拖慢性能

  • map 最慢,因为它的返回值是一个等长的全新的数组,数组创建和赋值产生的性能开销较大。

? 作    者:❣️

? 专    栏:

? 若有帮助,还请 关注➕点赞➕收藏  ,不行的话我再努努力???

   更多专栏订阅推荐:


✈️ 

?️ 

⭐️ 

✍️ 

?  

显示全文