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

news2024/11/23 19:38:09

在这里插入图片描述

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.coloradmin.cn/o/767175.html

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

相关文章

RS485远传电表有哪些功能?

RS485远传电表是一种具有远程传输功能的电表&#xff0c;可以通过RS485接口进行数据传输。它主要用于远程测量电能消耗、监测电力质量和实时控制电力负载等方面。 RS485远传电表具有多种功能&#xff0c;如&#xff1a; 1.远程测量电能消耗&#xff1a;RS485远传电表可以通过远…

【Linux工具】编译器、调式器、项目自动化构建工具以及git的使用3(GDB调试器的基础使用)

【Linux工具】编译器、调式器、项目自动化构建工具以及git的使用3&#xff08;GDB调试器的基础使用&#xff09; 目录 【Linux工具】编译器、调式器、项目自动化构建工具以及git的使用3&#xff08;GDB调试器的基础使用&#xff09;背景gdb的一些指令gdb实际运用显示代码运行程…

spring boot +vue 读取excel数据代码生成器

项目介绍 最近在开发工程中&#xff0c;需要根据excel中的数据生成标签类&#xff0c;手写太费劲啦&#xff0c;还得一边写一边对&#xff0c;受不了啦 决定写一个解析工具&#xff0c;自动生成代码 项目架构 项目采用springboot vue的开发方式&#xff0c;但vue并不是分离项目…

day38-Mybatis映射

0目录 Mybatis映射 1.2.3 1. Mybatis映射 1.1 映射文件XXMapper.xml语法 1.2 namespace&#xff1a;命名空间 namespace 的命名必须跟某个接口同名 1.3 id&#xff1a;命名空间中的唯一标识符 接口中的方法与映射文件中的SQL语句id一一对应 1.4 parameterType&#xf…

尚硅谷大数据Flink1.17实战教程-笔记03【Flink运行时架构】

尚硅谷大数据技术-教程-学习路线-笔记汇总表【课程资料下载】视频地址&#xff1a;尚硅谷大数据Flink1.17实战教程从入门到精通_哔哩哔哩_bilibili 尚硅谷大数据Flink1.17实战教程-笔记01【Flink概述、Flink快速上手】尚硅谷大数据Flink1.17实战教程-笔记02【Flink部署】尚硅谷…

好用的Net反编译工具,界面和VS差不多,供大家学习研究参考

1、无需设置 由于它是一个便携式工具&#xff0c;它不需要您将其安装在目标计算机上&#xff0c;因为只需拆包其存档并启动可执行文件即可完全访问其功能。 您还可以从可移动存储介质(如USB闪存驱动器或外部HDD)运行它。此外&#xff0c;它不会修改系统中的注册表项&#xff0c…

学习记录——SpectFormer、DilateFormer、ShadowFormer

SpectFormer: Frequency and Attention is what you need in a Vision Transformer, arXiv2023 频域混合注意力SpectFormer 2023 论文&#xff1a;https://arxiv.org/abs/2304.06446 代码&#xff1a;https://badripatro.github.io/SpectFormers/ 摘要视觉变压器已经成功地应用…

【Spring——Spring的基础与创建】

目录 &#x1f367;1. 什么是 Spring &#xff1f; &#x1fad6;1.1 容器 &#x1f359;1.2 IoC &#x1f97d;1.3 汽车类——传统写法 &#x1f358;1.4 汽车类——IoC 写法 &#x1f32d;2. 配置 maven 国内源 &#x1f32e;2.1 在设置中勾选文件 &#x1f364;2.2 在…

SpringCloud学习路线(4)—— Nacos注册中心

一、认识和安装Nacos &#xff08;一&#xff09;概念&#xff1a; Nacos是Alibaba的产品&#xff0c;现在是SpringCloud中的一个组件&#xff0c;相较于Eureka功能更加丰富。 &#xff08;二&#xff09;下载地址&#xff1a; https://github.com/alibaba/nacos/releases &am…

一文看懂《关于网络安全和信息化工作重要指示》

7月14日至15日&#xff0c;全国网络安全和信息化工作会议在京召开。《关于网络安全和信息化工作重要指示》也在会上得到解读与传达。 从近年来党的二十大等重大会议上网络安全和数据安全等相关话题多次被提及、我国陆续发布多部网络安全&数据安全相关政策法规等等&#xf…

个人微信号二次开发的实现,api接口

各位兄弟姐妹们大家好&#xff01;&#xff01;&#xff01;&#xff01; 我又瞧到了好玩的微信机器人分享给大家&#xff01; 社群运营这几年风头正盛&#xff0c;不能落伍啊&#xff0c;我们也赶紧组建了社群。 但是微信群还是社交属性为主的&#xff0c;当我们运营多个社群的…

(栈队列堆) 剑指 Offer 09. 用两个栈实现队列 ——【Leetcode每日一题】

❓ 剑指 Offer 09. 用两个栈实现队列 难度&#xff1a;简单 用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素&#xff0c;deleteHead …

如何通过振动传感器实现设备的故障诊断和预测性维护?

在现代工业生产中&#xff0c;设备的故障和停机时间对于企业的生产效率和经济效益有着巨大的影响。为了提高设备的可靠性和降低维护成本&#xff0c;越来越多的企业开始采用振动传感器作为关键的监测工具。振动传感器能够实时监测设备的振动情况&#xff0c;并通过数据分析和算…

自制编译器代码4.6含义

规则一&#xff0c;识别一个" 规则二&#xff0c;识别除了",,\n.\r的其他字符 规则三&#xff0c;这里第一个\意思是一个转义字符\&#xff0c;意思是ASCII码 比如\077就是八进制ASCII码的? 规则四&#xff0c;识别其他所有字符 规则五&#xff0c;回到defailt状态 …

不懂代码也不用怕!10款无代码网站搭建平台

作为设计师&#xff0c;对网站满脑子的构思&#xff0c;却受限于时间和技能&#xff08;比如写代码&#xff09;&#xff0c;这是何其无奈&#xff01;那个在你脑中盘桓许久的网站&#xff0c;或许是一个博客&#xff0c;可能是作品展示网站&#xff0c;但无论是哪种&#xff0…

华为OD机试真题 Java 实现【等差数列】【2023 B卷 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答…

GUI实例

运行代码&#xff1a; //GUI实例 #include"std_lib_facilities.h" #include"GUI/Simple_window.h" #include"GUI/GUI.h" #include"GUI/Graph.h" #include"GUI/Point.h"struct Lines_window :Window {Lines_window(Point xy…

《5.linux驱动开发-第2部分-5.2.字符设备驱动基础》最简单的模块源码分析 lsmod insmod modinfo rmmod dmesg

5.1.6.驱动应该这么学 5.1.6.1、先学好C语言 5.1.6.2、掌握相关预备知识 (1)硬件操作方面 (2)应用层API 5.1.6.3、驱动学习阶段 (1)注重实践&#xff0c;一步一步写驱动 (2)框架思维&#xff0c;多考虑整体和上下层 (3)先通过简单设备学linux驱动框架 (4)学会总结、记录&#x…

自动化测试框架性能测试报告模板

目录 一、项目概述 二、测试环境说明 三、测试方案 四、测试结果 五、结果分析 总结&#xff1a; 一、项目概述 1.1 编写目的 本次测试报告&#xff0c;为自动化测试框架性能测试总结报告。目的在于总结我们课程所压测的目标系统的性能点、优化历史和可优化方向。 1.2 …