js - 对forEach()函数的一些理解

在这里插入图片描述

1,定义和用法

定义:

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。注意: forEach() 对于空数组是不会执行回调函数的。

用法:

// 箭头函数
forEach((element) => { /* … */ })
forEach((element, index) => { /* … */ })
forEach((element, index, array) => { /* … */ })// 回调函数
forEach(callbackFn)
forEach(callbackFn, thisArg)// 内联回调函数
forEach(function(element) { /* … */ })
forEach(function(element, index) { /* … */ })
forEach(function(element, index, array){ /* … */ })
forEach(function(element, index, array) { /* … */ }, thisArg)

2,forEach是否会改变原数组?

结论:对于简单数据类型是不会改变原数组的,对于复杂数据类型的直接赋值操作则是可以改变原数组的;

1,简单数据类型不会改变原数组

      const arrNumber = [1, 2, 3, 4];arrNumber.forEach((item,index)=>{item = item*2})console.log("arrNumber:",arrNumber); // [1, 2, 3, 4]
  const arrString = ['Eula','Kaya','Umbar']arrString.forEach((item,index)=>{item = item+'_'+index})console.log("arrString:",arrString);// ['Eula','Kaya','Umbar']

那我如果就是想要改变原数组,可以这样写:

   const arrNumber = [1, 2, 3, 4];arrNumber.forEach((item,index,arr)=>{if(item % 2 === 0){console.log("可以被2整除的需要重新赋值:",item);arr[index] = 100/}})console.log("arrNumber:",arrNumber);//[1, 100, 3, 100]

直接 arr[index] ;相当于你平常的 数组名[第几项] = 值。这样自然是可以修改原数组的;

2,引用数据类型直接对其直接赋值能够改变原数组

const list = [{ name: "Kaya", age: 18 },{ name: "Eula", age: 19 },{ name: "Umbar", age: 20 }];// 直接进行赋值是可以改变原数组的 改变姓名list.forEach((item, index) => {if (item.name === "Eula") {item.name = "Xinjie";}});// 改变年龄list.forEach((item, index) => {item.age++;});console.log("list:", list);打印如下:0:{name: 'Kaya', age: 19}1: {name: 'Xinjie', age: 20}2: {name: 'Umbar', age: 21}

forEach() 相当于把原数组拷贝出来,对拷贝出来的数据进行操作,因为基本类型的数据相当于深拷贝,引用数据是浅拷贝,相当于只拷贝了指针地址,更改数据也会连带把原数组给改掉;

对于基本数据类型:number,string,Boolean,null,undefined它们在栈内存中直接存储变量与值。
而Object对象的真正的数据是保存在堆内存,栈内只保存了对象的变量以及对应的堆的地址,所以操作Object其实就是直接操作了原数组对象本身。

3,除了抛出异常以外,无法中止或跳出循环

forEach对数组进行遍历时,不能使用breakreturn等关键字跳出循环,使用return只能跳过本次循环,相当于continue。

1,使用return 跳出本次循环

  	  var arr = [1, 2, 3, 4, 5];arr.forEach(function (item) {// 只能跳出本次循环if (item === 3) {return;}console.log("item:",item); // 1 2  4 5});

2,抛出错误跳出终止整个循环(不推荐使用)

var arr = [1, 2, 3, 4, 5];try {arr.forEach(function (item) {// 只能跳出本次循环if (item === 3) {throw new Error("主动跳出循环");}console.log("item:", item); // 1 2 });} catch (error) {console.log("error:", error);}

注意:抛出异常虽然能够跳出整个循环体,但需要try catch函数来捕获此异常,否则控制台报错将会阻断代码的向下执行;

3,forEach()方法不支持使用break或continue语句来跳出循环或跳过某一项。

如果需要跳出循环或跳过某一项,应该使用for循环或其他支持break或continue语句的方法。

4,不能处理异步函数(async await)

1,先看下面这个案例:

async function test() {let arr = [3, 2, 1]arr.forEach(async item => {const res = await mockSync(item)console.log(res)})console.log('end')
}function mockSync(x) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(x)}, 1000 * x)})
}
test()
我们期望的结果是:
3
2 
1
end
但是实际上会输出:
end
1
2
3

2,针对上面问题可以有以下两种解决方案:

第一种:使用普通的for循环语法

 function mockSync(x) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(x);}, 1000 * x);});}// 使用for循环async function test(){let arr = [3, 2, 1];for(let i=0;i<arr.length;i++){const res = await mockSync(arr[i]);console.log(res);}}test();// 3,2,1

现在执行顺序是正常的:等待3秒后打印3,然后等待2秒后打印2,最后等待1秒后打印1;

第二种:使用for of 循环来处理异步函数

   function mockSync(x) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(x);}, 1000 * x);});}// 使用for of 循环async function test() {let arr = [3, 2, 1];for (const item of arr) {const res = await mockSync(item);console.log("res:",res);}}test();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/2844.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在uni-app中,如果data中的对象属性改变了,但是页面没有相应更新的情况,通常有以下几点需要注意:

1. 使用this.$set更新对象属性直接修改对象属性是无法触发页面更新的,需要使用this.$set方法: this.$set(this.obj, key, value) 2. 确保数据层级不太深如果对象层级过深,改变内层属性也可能无法触发更新。建议关键数据不要超过2层。 3. 使用深度 watcher可以在watch中用深度…

mcu 启动流程

MCU启动流程 MCU启动流程 MCU启动流程1 MCU的启动方式2 MCU程序启动执行过程3 启动过程的执行工作4 keil调式过程验证5 调试文件map 1 MCU的启动方式 单片机的启动方式&#xff0c;以stm32为例&#xff0c;如下&#xff1a; 不同的下载方式对应的不同的启动方式&#xff0c;st…

truffle 进行智能合约测试

本方法使用了可视化软件Ganache 前两步与不使用可视化工具的步骤是一样的&#xff08;有道云笔记&#xff09;&#xff0c;到第三步的时候需要注意&#xff1a; 在truffle插件下找到networks目录&#xff0c;提前打开Ganache软件 在Ganache中选择连接或者新建&#xff0c;我在…

如何学习Java集合框架? - 易智编译EaseEditing

要学习Java集合框架相关的技术和知识&#xff0c;可以按照以下步骤进行&#xff1a; 掌握Java基础知识&#xff1a; 在学习集合框架之前&#xff0c;确保你已经具备良好的Java编程基础&#xff0c;包括语法、面向对象编程&#xff08;OOP&#xff09;原理和常用的核心类库等。…

MySQL备份与还原/索引/视图

MySQL备份与还原/索引/视图练习 文章目录 一、备份与还原1、使用mysqldump命令备份数据库中的所有表2、备份booksDB数据库中的books表3、使用mysqldump备份booksDB和test数据库4、使用mysqldump备份服务器中的所有数据库5、使用mysql命令还原第二题导出的book表6、进入数据库使…

Gnina split_caffe_proto.py

1. 导入必要的模块&#xff1a;mmap、re、os、errno。 2. 获取当前脚本所在路径的绝对路径作为script_path。 3. 创建用于存放caffe.proto片段的目录结构。脚本尝试创建../docs/_includes/和../docs/_includes/proto/两个目录&#xff0c;若目录已存在则忽略&#xff0c;若创…

STM32案例学习 GY-39环境监测传感器模块

STM32案例学习 GY-39环境监测传感器模块 硬件平台 野火STM32F1系列开发板正点STM32F1系列开发板STM32F103ZET6核心板GY-39环境监测传感器模块 GY-39环境监测传感器模块 GY-39 是一款低成本&#xff0c;气压&#xff0c;温湿度&#xff0c;光强度传感器模块。工作电压 3-5v…

thinkphp 上传图片

public function upload_img(){// 读取图片资源// 存储路径$path "uploads/avatar";$file request()->file(background_img);// 存储图片$info $file->rule(uniqid)->move($path);// 存储成功if ($info) {//获取到上传图片的路径名称$name_img $path . …

linux查看ipynb文件

linux查看ipynb文件 使用jupyter查看 使用jupyter查看 安装 pip install jupyter添加配置好的环境到jupyter notebook的kernel中&#xff1a; python -m ipykernel install --user --name mmdet --display-name "mmdet"运行jupyter notebook &#xff08;在ipynb…

WebSocket理论和实战

一 WebSocket理论 1.1 什么是http请求 http链接分为短链接、长链接&#xff0c;短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持链接&#xff08;但是是单向的&#xff0c;只能从客户端向服务端发消息&#x…

pycharm import的类库修改后要重启问题的解决方法

通过将以下行添加到pycharm中的settings-> Build,Excecution,Deployment-> Console-> Python Console中&#xff0c;可以指示Pycharm在更改时自动重新加载模块&#xff1a; %load_ext autoreload %autoreload 2

ubuntu 设置系统时间矫正

1、安装ntpdate&#xff0c;同步标准时间 2、修改时区 3、在.profile文件中写入上面提示的信息&#xff0c;保存退出、更新配置文件或者重启生效 3.1、或者配合上面的cp那条命令&#xff0c;用下面的命令保存到底层 $ hwclock --systohc 4、重启之后&#xff0c;查看日期时间已…

中间件上云部署 rocketmq

中间件上云部署 rocketmq rocketmq部署一、rokectmq介绍二、rokectmq特性三、使用rocketmq理由四、rocketmq 核心概念五、rocketmq角色六、rocketmq集群部署方式七、rocketmq集群部署7.1 环境说明7.2 构建rocketmq镜像7.3 获取rocketmq-dashboard镜像7.4 rocketmq部署描述文件编…

linux安装mysql以及使用navicat连接mysql

目录 一、下载mysql 二、安装mysql 三、使用Navicat连接MySQL 四、常见问题 1、启动服务时报错 Failed to start mysql.service: Unit not found. 的解决方法。 2、登录过程出现&#xff1a;access denied for user’root’‘localhost’(using password:Yes) 的解决方…

Redis的缓存问题

说起Redis的缓存&#xff0c;我们知道前端发出的请求到后端&#xff0c;后端先从Redis中查询&#xff0c;如果查询到了则直接返回&#xff0c;如果Redis中未查询到&#xff0c;就去数据库中查询&#xff0c;如果数据库中存在&#xff0c;则返回结果并且更新到Redis缓存当中&…

Softmax函数

S o f t m a x Softmax Softmax 函数是一种常用的激活函数&#xff0c;通常用于多类别分类问题中。它的原理是将一个向量的元素转化为概率分布&#xff0c;使得每个元素的取值范围在0到1之间&#xff0c;并且所有元素的和为1。 S o f t m a x Softmax Softmax 函数的作用是将原…

<JAVA学习笔记>SpringBoot中的@Retryable重试注解

Retryable注解的功能顾名思义&#xff0c;即重试。它可以作用在方法上&#xff0c;当方法抛出指定的异常时&#xff0c;整个方法将会被重新执行。在使用时需要先在pom.xml中导入相关依赖&#xff0c;再在启动类中添加EnableRetry注释以开启重试功能&#xff0c;最后在相应的方法…

《遗留系统现代化》读书笔记(基础篇)

目录 为什么要对遗留系统进行现代化&#xff1f; 什么是遗留系统&#xff1f; 遗留系统的现代化价值 总结 遗留系统的四化建设 代码现代化 架构现代化 DevOps 现代化 团队结构现代化 总结 本文地址&#xff1a;《遗留系统现代化》读书笔记&#xff08;基础篇&#xff…

通讯录(纯C语言实现)

相信大家都有过通讯录&#xff0c;今天我来带大家实现以下最简单的通讯录&#xff0c;通过本篇文章&#xff0c;相信可以让大家对C语言有进一步的认识。 话不多说&#xff0c;我们先放函数的实现 #define _CRT_SECURE_NO_WARNINGS 1 #include "Contact.h"int Chea…

【集合排序】List根据对象某一字段排序的六种方法

目录 1.使用List的sort()方法&#xff0c;自定义一个Compartor比较器 2.使用List的sort()方法&#xff0c;Lambda表达式写法【写法很简单&#xff0c;推荐】 3.使用Collections.sort()方法【重写Comparable接口】 4.使用Collections.sort()方法【自定义Compartor比较器】 …