javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JS中map和forEach区别

JavaScript中map和forEach的区别示例详解

作者:~嘻嘻哈哈~

在JavaScript中forEach和map是两种常见的数组迭代方法,它们允许开发者遍历数组的每一个元素,这篇文章主要介绍了JavaScript中map和forEach区别的相关资料,需要的朋友可以参考下

一、本质区别

1. 返回值不同

  • map返回回调函数对每个元素处理后的新数组。
  • forEach返回undefined
const arr = [1, 2, 3];
 // [3, 6, 9]
const arr_1= arr.map(item => item * 3);
// undefined
const arr_2= arr.forEach(item => item  * 2); 

2. 是否可​​链式调用

  • map返回新数组,可链式调用,可用其他数组方法(如filterreduce)。
  • forEach返回undefined,不可链式调用​​​​​
const arr = [1, 2, 3];
// 可链式调用
[6, 9]
arr.map(item  => item * 3).filter(x => x > 3);
// Cannot read property 'filter' of undefined
arr.forEach(item => item * 3).filter(x => x > 3);

二、是否修改原数组

1. map

1. 当原数组元素是​基本数据类型​​(如数字、字符串、布尔值),会生成新数组,不改变原数组。

const arr = [1, 2, 3];
const arr_1 = arr .map(item => item * 2);
// [1, 2, 3]
console.log(arr); 
// [2, 4, 6]
console.log(arr_1); 

2. 当原数组元素是引用数据类型​​(如对象、数组)时,会生成新数组,若回调函数中直接修改其元素属性​,可改变原数组(因其元素是引用的)。

const names= [{ name: 'zhangsan' }, { name: 'lisi' }];
const names_1 = names.map(item=> {
  // 直接修改原对象属性
  item.name = 'wangwu'; 
  return item;
});
// [{ name: 'wangwu' }, { name: 'wangwu' }]
console.log(names);
// [{ name: 'wangwu' }, { name: 'wangwu' }]
console.log(names_1); 

3. 当原数组元素是引用数据类型​​(如对象、数组)时,会生成新数组,若回调函数中创建新对象/数组,不改变原数组。

const names= [{ name: 'zhangsan' }, { name: 'lisi' }];
const names_1 = names.map(item=> ({ ...item, age: 21 }));
// [{ name: 'wangwu' }, { name: 'lisi' }]
console.log(names); 
//[{ name: 'zhangsan', age: 21 }, { name: 'lisi', age: 21 }]
console.log(names_1);

4. 总结:​​map本身不改变原数组​​,若回调函数中对引用数据类型修改,可改变原数组。

2. forEach

1. 当原数组元素是​​基本数据类型​​(如数字、字符串、布尔值),不改变原数组。

const arr = [1, 2, 3];
arr.forEach(item => item *= 2);
// [1, 2, 3]
console.log(arr); 

2. 当原数组元素是引用数据类型​​(如对象、数组)时,修改其元素属性​,可改变原数组(因其元素是引用的)。

let names= [{ name: 'zhangsan' }, { name: 'lisi' }];
names.forEach((item, index, array) => {
  array[index] = 'wangwu'; 
  // 或
  item.name = 'wangwu'
});
// [{ name: 'wangwu' }, { name: 'wangwu' }]
console.log(names);

3. 当原数组元素是引用数据类型​​(如对象、数组)时,​直接替换整个元素对象,不改变原数组(形参是原元素的副本)

let names= [{ name: 'zhangsan' }, { name: 'lisi' }];
names.forEach(item => item = { name: 'xiaohong' });
// [{ name: 'zhangsan' }, { name: 'lisi' }];
console.log(names);

4. 总结:​forEach,修改​基本数据类型​元素的值,或直接替换引用数据类型元素​​,不改变原数组。修改引用数据类型​元素的属性,​可改变原数组。

三、使用场景 

​​map​​使用场景​​:需生成新数组(如数据转换、提取属性)或需链式调用其他方法时。

// [2, 4, 6]
const arr = [1, 2, 3].map(x => x * 2); 

​​forEach​​使用场景​​:无需新数组,需如打印、修改外部变量时。

let sum = 0;
// 6
[1, 2, 3].forEach(item => sum += item);

四、forEach使用限制 

1. 无法中断或跳过循环

不支持使用break或continue语句来中断或跳过循环,可通过forfor...of解决。或抛出异常解决。

// 抛出异常解决
let arr = [1, 2, 3];
try {
    arr.forEach(item => {
        if (item === 2) {
            throw('error');
        }
        console.log(item);
    });
} catch(e) {
    console.log(e);
}
// 1
// error

2.不支持处理异步函数

forEach是同步方法,在其中执行异步函数,不会等待异步函数完成,会立即处理下一个元素,无法保证执行顺序,可通过for...of解决。

async function handleArr(arr) {
    arr.forEach(async item => {
        const res = await asyncData(item);
        console.log(res);
    });
    console.log('end');
}
 
function asyncData(x) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(x);
        }, 1000 * x);
    });
}
handleArr([1, 2, 3]);
// 预期
1
2
3
end

// 实际
end
3
2
1

3.无法捕获异步函数中错误

即使异步函数在执行过程中抛出错误,forEach仍继续处理下一个元素,不会处理错误。

4. 遍历过程中更改索引无效 

forEach中索引是自动管理的,每次遍历时自动递增,可通过for解决。

// 1. 试图直接更改索引
let arr = [1, 2, 3, 4];
arr.forEach((item, index) => {
    // 1 2 3 4
    console.log(item); 
    index++;
});

// 2. 试图删除元素更改索引
let arr_1 = [1, 2, 3, 4];
arr_1.forEach((item, index) => {
    if (item === 2) {
        // 删除元素2
        arr.splice(index, 1); 
    }
    // [0, 1] [1, 2] [2, 4]
    console.log([index, item]); 
});
// [1, 3, 4]
console.log(arr_1);

// 3. for解决
let arr_2 = [1, 2, 3, 4];
for (let i = 0; i < arr_2.length; i++) {
    if (arr_2 [i] === 2) {
        // 删除元素2
        arr_2.splice(i, 1); 
        i--;
    } else {
        // 1 3 4
        console.log(arr_2[i]); 
    }
}
// [1, 3, 4]
console.log(arr_2); 

总结 

到此这篇关于JavaScript中map和forEach的区别详解的文章就介绍到这了,更多相关JS中map和forEach区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文