面试题:问js的forEach和map的区别
前端面试题库 (面试必备) 推荐:★★★★★
地址:前端面试题库
【国庆头像】- 国庆爱国 程序员头像!总有一款适合你!
前言
为什么要写这么一篇文章,原因是今天下午水群的时候,有个小伙伴分享自己的面试题,其中一个是foreach
和map
的区别,其实是蛮简单,蛮基础的一道题,但是他是这么回答的
一个会改变原数组,一个不会
我当场就懵了,我以为是整活,谁知道是认真的,并且给我发了一篇文章
我看完更蚌埠住了,那么多对的文章,你偏偏挑个错的
然后我发现,真的很多人都这么认为的,那这真的是一件很可怕的事情,明明你自己试一下就知道了,甚至有不少文章都是这么写的,但是我也看到了不错的文章,写的已经不错了
那么咱们,就这个简单的问题,咱们浅浅地说一下~
区别
map
会返回一个新的数组,而forEach
不会
简单的区别我们可以在MDN
上看看
简单来说什么意思,map
会返回一个新的数组,而forEach
不会,实际上是因为forEach
不会返回任何值(实际上返回的是undefined
),而map
是有返回值的,是一个新数组
我们可以简单手写一下,看的会更直观一些
map
function myMap(array, callback) {const result = [];for (let i = 0; i < array.length; i++) {result.push(callback(array[i], i, array));}return result;
}
forEach
function myForEach(array, callback) {for (let i = 0; i < array.length; i++) {callback(array[i], i, array);}
}
再简单点对比
forEach
和map
的实现原理相似。它们都是通过遍历数组,对数组的每个元素执行特定的函数。区别主要在于它们处理函数返回值的方式不同。forEach
忽略函数的返回值,而map
则将函数的返回值收集到一个新的数组中。
在内部,这两个函数可能会使用一个类似于下面的for
循环来遍历数组:
for (let i = 0; i < array.length; i++) {callback(array[i], i, array); // callback 是 forEach 或 map 的参数函数
}
在 map
的内部实现中,还会有一个新的数组用于收集每次调用回调函数的结果。这个新的数组最后会被返回:
let newArray = [];
for (let i = 0; i < array.length; i++) {newArray.push(callback(array[i], i, array)); // callback 是 map 的参数函数
}
return newArray;
那么这个时候,有人可能会想,那我使用
forEach
的时候,加个return
不就得了,咱们先不说能不能实现,就是真实现了,我觉得是没什么实际意义的,尽管你可以在回调函数中添加返回语句,但这个返回值不会被forEach
方法捕获或使用
那接下来咱们看看能不能实现吧
const array = [1, 2, 3]const result = array.forEach((element) => {return element * 2; // 这个返回值不会被 forEach 捕获或使用});console.log(result); // 输出: undefined
那么咱们使用map
呢
const array = [1, 2, 3]const result = array.map((element) => {return element * 2; // 这个返回值会被 map 捕获或使用});console.log(result); // 输出: [2, 4, 6]
到这里,我相信大家就能明白了
map和forEach会不会改变原数组
这需要看我们面对的数据类型,会分为基础数据类型
和引用类型
基础数据类型
forEach
const array = [1, 2, 3, 4];array.forEach(item => {item = item + 1})console.log(array); // [1,2,3,4]
map
const array = [1, 2, 3, 4];array.map(item => {item = item + 1})console.log(array); // [1,2,3,4]
我们发现是不会进行改变的
引用类型
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
就不再写了,也是会改变的
所以重点来了,我们回到这个问题:问js的forEach和map的区别
,显而易见一个会改变原数组,一个不会
这个答案毫无疑问是错误的
这里我们其实应该思考的是,为什么基础数据类型不会更改,引用类型会更改
这是因为在使用 forEach
和 map
方法时,对引用类型
元素的修改会直接反映在原始数组
中。这是因为引用类型的元素实际上存储的是引用(内存地址
),而非值本身
。因此,通过引用
可以访问和修改原始数组
中的元素。
而number,string,Boolean,null,undefined
它们在栈内存中直接存储变量与值
我们再回头看这个
为什么他这个修改了呢
因为使用的是
arr[index]
。相当于你平常的数组名[第几项] = 值
。这样自然是可以修改的。
还有哪些区别呢
- foreach可以跳出循环,
return
语句可以当前回调函数中返回,而map不能,只能遍历完整个数组。 - foreach不支持链式调用,而map支持链式调用,可以继续对返回的新数组进行操作。
这里注意:forEach
方法无法通过使用 break
语句来中断循环。 break
语句用于中断循环的功能只适用于 for
循环或 while
循环
这里给大家点例子吧,一下就能看懂了
// 使用 forEach 跳出当前循环const array1 = [1, 2, 3, 4, 5];let sum1 = 0;array1.forEach((element) => {if (element === 3) {return; // 使用 return 跳出循环}console.log(element); //1,2,4,5sum1 += element;});console.log(sum1); // 输出: 12// 使用 map 无法中断循环const array2 = [1, 2, 3, 4, 5];const newArray = array2.map((element) => {if (element === 3) {// 使用 return 语句无法中断 map 循环return;}return element * 2;});console.log(newArray); // 输出: [2, 4, undefined, 8, 10]// map 方法支持链式调用const array3 = [1, 2, 3, 4, 5];const doubledSum = array3.map((element) => element * 2).reduce((accumulator, currentValue) => accumulator + currentValue, 0);console.log(doubledSum); // 输出: 30
const array = [1, 2, 3, 4, 5];let sum = 0;array.forEach((element) => {if (element === 3) {break; // 使用 break 无法中断 forEach 循环}sum += element;});console.log(sum); // 此行代码不会执行,因为上面的代码会抛出错误//for循环则可以const array = [1, 2, 3, 4, 5];let sum = 0;for (let i = 0; i < array.length; i++) {const element = array[i];if (element === 3) {break; // 使用 break 中断 for 循环}sum += element;}console.log(sum); // 输出: 3
作为数组
最常见的几个api
之一,我觉得搞懂它是有必要的,当然,我这里说的其实是不全的,因为网上的文章较多,文档也很详细,这篇文章主要的目的是帮助一些小伙伴纠正一下~
最后,如有哪里不正确,请您指正~
致谢补充
这里是文章发出一段时间的致谢补充,很感谢评论区的一些建议和指正,主要是我在forEach
这里,说出了它可以跳出循环(本次循环),大家进行了指正
前端面试题库 (面试必备) 推荐:★★★★★
地址:前端面试题库
【国庆头像】- 国庆爱国 程序员头像!总有一款适合你!
相关文章:

面试题:问js的forEach和map的区别
前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 【国庆头像】- 国庆爱国 程序员头像!总有一款适合你! 前言 为什么要写这么一篇文章,原因是今天下午水群的时候&…...

Hadoop设置固定ip无效的解决办法
今天配置Hadoop的时候,执行vi /etc/sysconfig/network-scripts/ifcfg-ens33修改网络配置文件后,一切正常,但重启后IP改变了,并且在修改以及重启网络连接数次后,IP依旧不按照我在ifcfg-ens33中配置的那样,检…...

论文解读 | 用于3D对象检测的PV-RCNN网络原创
原创 | 文 BFT机器人 01 背景 本文的背景涉及到3D物体检测,这是一个在自动驾驶和机器人等领域应用广泛的重要问题。在这些领域,LiDAR传感器被广泛用于捕捉3D场景信息,生成不规则且稀疏的点云数据。这些点云数据提供了理解和感知3D场景的关键…...

kali安装volatility及插件mimikatz
1.准备工作 kali安装pip2 wget https://bootstrap.pypa.io/pip/2.7/get-pip.py python2 get-pip.py 查看pip2版本 python2 -m pip -v pip2安装升级 pip2 install --upgrade setuptools 安装2个库 pip2 install construct2.10.54 pip2 install pycryptodome 下载文件d…...
什么是阻塞队列?如何使⽤阻塞队列来实现⽣产者-消费者模型?哪个阻塞队列最常用?
阻塞队列 阻塞队列(Blocking Queue)是一种特殊类型的队列,它具有阻塞特性,即当队列为空时,试图从队列中取出元素的操作会被阻塞,直到队列中有元素可取。同样,当队列已满时,试图将元素放入队列的操作也会被阻塞,直到队列有空闲空间。 JDK 7引入了7个阻塞队列,它们都…...

Bean拷贝组件(注解驱动)方案设计与落地
一、背景 数据流转在各层之间的过程,应当是改头换面的,字段属性数量,属性名称(一般不变,但也有重构时出现变化的情况),类型名称(普遍变化例如BO、VO、DTO)。对于转换的业…...

hive的建表语句
hive建表语句CREATE TABLE ccwn_zh_event_push (customerid string,cardnumber string,accountnumber string,eventcode string,eventtime string,activities string,activityRefuseCode string,lables string)PARTITIONED BY(dt string)ROW FORMAT SERDE org.apache.hadoop.hi…...

提升效率:PostgreSQL准确且快速的数据对比方法
作为一款强大而广受欢迎的开源关系型数据库管理系统,PostgreSQL 在数据库领域拥有显著的市场份额。其出色的可扩展性、稳定性使其成为众多企业和项目的首选数据库。而在很多场景下(开发|生产环境同步、备份恢复验证、数据迁移、数据合并等)&a…...

【轻NAS】Windows搭建可道云私有云盘,并内网穿透公网访问
文章目录 1.前言2. Kodcloud网站搭建2.1. Kodcloud下载和安装2.2 Kodcloud网页测试 3. cpolar内网穿透的安装和注册4. 本地网页发布4.1 Cpolar云端设置4.2 Cpolar本地设置 5. 公网访问测试6.结语 1.前言 云存储作为近些年兴起的概念,成功吸引了各大互联网厂商下场&…...

计算机网络 第一章:概述
目录 一.因特网概述 1.1网络、互联网(互连网)和因特网 1.2internet与Internet的区别 1.3因特网服务提供者ISP(Internet Service Provider) 1.4因特网组成 二.三种交换方式 2.1电路交换 2.2分组交换(重点) 2.3报文交换 三.计算机网络的定义和分类 四.计算机网络的性能…...
centos7 firewalld ip转发设置、安装docker-compose出现错误、docker-compose部署Yapi
一 centos7 firewalld ip转发设置 #!/bin/bash #开启系统路由模式功能 vim /etc/sysctl.conf #添加下面一行 net.ipv4.ip_forward1 #运行这个命令会输出上面添加的那一行信息,意思是使内核修改生效 sysctl -p #开启firewalld systemctl start firewalld #防火墙开启…...

Cglib代理和JDK代理原理的区别
一、JDK Jdk动态代理,拿到目标类所继承的接口,生成代理类,并且代理类也会实现和目标类一样的接口。 二、Cglib Cglib代理功能更强,无论目标类是否实现接口都可以代理,他是基于继承的方式类代理目标类,如果…...

论文阅读-A General Language for Modeling Social Media Account Behavior
论文链接:https://arxiv.org/pdf/2211.00639v1.pdf 目录 摘要 1 Introduction 2 Related work 2.1 Automation 2.2 Coordination 3 Behavioral Language for Online Classification 3.1 BLOC alphabets 3.1.1 Action alphabet 3.1.2 Content alphabets 3.…...

Python中的异常处理4-3
在《Python中的异常处理4-2》中提到,except语句后面可以加上具体的异常类型。有时我们需要这个异常的其他细节,此时可以使用except...as语句。 1 except...as语句 except..as语句的格式为 except 异常类型 as 异常实例名 从以上格式中可以看到&#…...

Swift学习内容精选(一)
Swift 可选(Optionals)类型 Swift 的可选(Optional)类型,用于处理值缺失的情况。可选表示"那儿有一个值,并且它等于 x "或者"那儿没有值"。 Swfit语言定义后缀?作为命名类型Optional的简写&…...

Marin说PCB之封装设计系列---(02)--异形焊盘的封装设计总结
每天下班回家看电视本来是一件很美好的事情,可是正当我磕着瓜子看着异人之下的时候,手机突然响起来了,我以为是我们组哪个同事找我呢。一接电话居然是我的老朋友陈世美陈总,江湖人称少妇杀手。给我打电话主要是说他最近遇到一个异…...

SpringBoot使用AOP详解
目录 1 AOP是什么2 AOP概念3 Springboot中使用AOP4 AOP原理5 应用场景 1 AOP是什么 AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续&…...
【Qt】QGroundControl入门1:介绍
1、简介 1.1 QGroundControl QGroundControl是一款开源的无人机地面控制站软件,依赖Qt库,简称QGC。 QGroundControl为任何支持 MAVLink协议 的无人机提供完整的飞行控制和任务规划。QGroundControl为 PX4 和 ArduPilot 驱动的无人机提供驱动配置。 源码:https://github.co…...

第36章_瑞萨MCU零基础入门系列教程之步进电机控制实验
本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id728461040949 配套资料获取:https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总: ht…...
198.打家劫舍,213.打家劫舍II,337.打家劫舍III
代码随想录训练营第48天|198.打家劫舍,213.打家劫舍II,337.打家劫舍III 198.打家劫舍文章思路代码 213.打家劫舍III文章思路代码 337.打家劫舍III文章思路代码 总结 198.打家劫舍 文章 代码随想录|0198.打家劫舍 思路 d p [ i ] M a x ( d p [ i − …...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...