【深入探讨】JavaScript 中的 forEach 和 map 区别

🐱 个人主页:不叫猫先生,公众号:前端Clodplay
🙋‍♂️ 作者简介:前端领域优质作者、阿里云专家博主,共同学习共同进步,一起加油呀!
✨优质专栏:VS Code插件开发极速入门
📢 资料领取:前端进阶资料可以找我免费领取

在这里插入图片描述

区别

map会返回一个新的数组,而forEach不会具体探讨一下,实则会有新的发现!

下面来探讨一下原因

手写 map 和 forEach

手写map,如下:

function myMap(array, callback) {
  //存储结果
  const result = [];
  for (let i = 0; i < array.length; i++) {
    result.push(callback(array[i], i, array));
  }
  return result;
}

调用上面的myMap函数

// 定义一个回调函数,用于对数组元素进行操作
function double(value) {
  return value * 2;
}

// 定义一个数组
const numbers = [1, 2, 3, 4, 5];

// 调用 myMap 函数,并传入定义好的回调函数
const doubledNumbers = myMap(numbers, double);

console.log(doubledNumbers); // 输出 [2, 4, 6, 8, 10]

手写forEach,如下:

function myForEach(array, callback) {
  for (let i = 0; i < array.length; i++) {
    callback(array[i], i, array);
  }
}

调用上面的myForEach函数

// 定义一个回调函数,用于对数组元素进行操作
function logItem(item, index) {
  console.log(`Index ${index}: ${item}`);
}

// 定义一个数组
const fruits = ["Apple", "Banana", "Orange", "Mango"];

// 调用 myForEach 函数,并传入定义好的回调函数
myForEach(fruits, logItem);

总结:
上面可以看到 forEach 和 map 的实现原理相似。它们都是通过遍历数组,对数组的每个元素执行特定的函数。区别主要在于它们处理函数返回值的方式不同
forEach 忽略函数的返回值,而 map 则将函数的返回值收集到一个新的数组中

可以看到 map 和 forEach都会有一个for循环处理,且map有return

 for (let i = 0; i < array.length; i++) {
    result.push(callback(array[i], i, array));
  }
for (let i = 0; i < array.length; i++) {
    callback(array[i], i, array);
  }

那么能不能forEach也return,测试一下

        const array = [1, 2, 3]

        const result = array.forEach((element) => {
            return element * 2; // 这个返回值不会被 forEach 捕获或使用
        });

        console.log(result); // 输出: undefined

但是map,return 之后是有值的

        const array = [1, 2, 3]

        const result = array.map((element) => {
            return element * 2; // 这个返回值会被 map 捕获或使用
        });

        console.log(result); // 输出: [2, 4, 6]

map 和 forEach 会不会改变原数组

map 和 forEach 会不会改变原数组,需要看数据类型,具体分为基础数据类型和引用类型。

处理基本类型数据

forEach 处理基本数据类型

        let array = [1, 2, 3, 4];
        array.forEach(item => {
            item = item + 1
        })
        console.log(array); // [1,2,3,4]

map 处理基本数据类型

        let array = [1, 2, 3, 4];
        array.map(item => {
            item = item + 1
        })
        console.log(array); // [1,2,3,4]

测试后发现,都没有改变原数组

处理引用类型数据

forEach 处理引用类型数据

        const arr = [{
            name: 'shaka',
            age: 23
        }, {
            name: 'virgo',
            age: 18
        }]
        arr.forEach(item => {
            if (item.name === 'shaka') {
                item.age = 100
            }
        })
        console.log(arr); //[{name: 'shaka', age: 100}, {name: 'virgo', age: 18}]

在这里插入图片描述
map 处理引用类型数据

 const arr = [{
            name: 'shaka',
            age: 23
        }, {
            name: 'virgo',
            age: 18
        }]
        arr.map(item => {
            if (item.name === 'shaka') {
                item.age = 100
            }
        })
        console.log(arr); //[{name: 'shaka', age: 100}, {name: 'virgo', age: 18}]

在这里插入图片描述
发现都改变了原数据

思考:为什么基础数据类型不会更改原数据,引用类型不会

这是因为在使用 forEach 和 map 方法时,对引用类型元素的修改会直接反映在原始数组中。这是因为引用类型的元素实际上存储的是引用(内存地址),而非值本身。因此,通过引用可以访问和修改原始数组中的元素。而number、string、Boolean、null、undefined它们在栈内存中直接存储变量与值。

具体解释如下:
基本数据类型为值传递,callback的执行和原数组毫不相干,所以forEach无法修改基本数据的数组
基本数据类型(Primitive data types)如数值(Number)、字符串(String)、布尔值(Boolean)、null 和 undefined 等,它们在内存中是直接存储变量的值,而不是引用。因此,对于基本数据类型,当它们作为数组的元素被传递给 forEach 或 map 方法时,处理的是它们的值的拷贝,而不是原始值本身。因此,对于基本数据类型,任何更改都只是在处理的拷贝上进行,不会影响到原始数组中的值。


引用类型(Reference types)如对象(Object)、数组(Array)和函数(Function)等,它们在内存中存储的是地址,即指向存储实际数据的内存地址。因此,当引用类型的元素被传递给 forEach 或 map 方法时,处理的是对该地址的引用,而不是原始数据本身。这意味着对引用类型的元素进行的任何更改都会直接反映在原始数组中,因为它们都指向相同的内存地址。

好书推荐

《ReactJS入门实践》
在这里插入图片描述
本书涵盖了编写高质量React代码要掌握的一切内容。你将学习使用函数方法和类方法编写React组件;学习如何使用几种不同的方法来管理应用程序的状态,包括使用React Hooks和setState方法;学习如何将组件合在一起来创建完整的动态用户界面;还将学习如何从外部数据源获取数据并在应用程序中使用。此外,本书介绍了如何在用户的Web浏览器中存储数据,以提高应用程序的性能和可用性。谈到可用性,你将会了解在移动设备和桌面上运行应用程序的最佳实践,还将了解如何确保应用程序可访问。

如果你对《ReactJS实践入门》感兴趣的话,可以点击链接购买:链接直达

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不叫猫先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值