js中的遍历方法比较:map、for...in、for...of、reduce和forEach的特点与适用场景

news2024/9/28 1:18:44

在这里插入图片描述

😊博主:小猫娃来啦
😊文章核心:JavaScript中的遍历方法比较:map、for…in、for…of和forEach的特点与适用场景

文章目录

  • map 方法
    • 概述
    • 用法
    • 返回值特点
  • for...in 循环
    • 概述
    • 用法
    • 注意事项
  • for...of 循环
    • 概述
    • 用法
    • 可迭代对象
  • forEach 方法
    • 概述
    • 用法
    • 注意事项
  • reduce()方法
    • 概述
    • 用法
    • 注意事项
  • 对比与选择

map 方法

概述

map 方法是 JavaScript 数组提供的高阶函数之一,它接受一个函数作为参数,并对数组中的每个元素执行该函数。通过这种方式,开发者可以轻松地对数组元素进行转换或生成新的数组,而不需要编写显式的循环。

用法

使用 map 方法的关键是理解传递给它的函数。这个函数通常称为映射函数,它定义了对数组中每个元素的操作或转换。映射函数接受三个参数:当前正在处理的元素、当前元素的索引和操作的原始数组。
具体使用 map 方法的步骤如下:

定义映射函数,可使用匿名函数或命名函数。
调用数组的 map 方法,将映射函数作为参数传入。

例如,我们想将数组中的每个元素都加倍,可以定义以下映射函数:

function double(element) {
  return element * 2;
}

然后,我们可以使用 map 方法将映射函数应用于数组:

const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map(double);

这个小例子中,map 方法会对 numbers 数组中的每个元素调用映射函数 double,并将返回值组成一个新的数组 doubledNumbers。

返回值特点

map 方法的返回值特点在于它返回一个全新的数组,而不会改变原始数组。这意味着原始数组保持不变,而生成的新数组包含经过映射函数处理后的元素。因此,map 方法是一种纯函数,不会对原始数据进行修改。

此外,由于 map 方法返回的是一个新数组,我们可以链式调用其他数组方法,如 filter、reduce 等,以进一步处理数据。这种方法的组合和链式调用能够提高代码的可读性和维护性。

需要注意的是,map 方法只会遍历已存在的数组元素,而不会执行已删除或未赋值的项。如果数组中的元素被修改或删除,在执行映射函数时会影响到 map 方法的结果。


for…in 循环

概述

for…in 循环是一种遍历对象属性的迭代循环,它通常用于遍历普通对象或数组等可迭代的结构。与传统的 for 循环或 forEach 方法不同,for…in 循环主要用于迭代对象的键(属性名),而非数组的索引或元素值。它提供了一种简洁且易于使用的方式来访问对象的属性。

用法

使用 for…in 循环的关键是理解其基本语法和用法。for…in 循环语法如下:

for (variable in object) {
   // 在此处执行操作
}

其中,variable 是一个变量,代表当前循环迭代的属性名;object 是要迭代的对象。

接下来,我们通过一个小例子来演示 for…in 循环的用法:

const person = {
  name: 'Alice',
  age: 30,
  gender: 'female'
};

for (let key in person) {
  console.log(key + ': ' + person[key]);
}

这个小例子中,我们定义了一个名为 person 的对象,然后使用 for…in 循环遍历 person 对象的属性。循环体内的语句 console.log(key + ': ' + person[key]) 输出了每个属性名和对应的属性值。

注意事项

在使用 for…in 循环时,有一些需要注意的事项:

  • 迭代顺序不确定:for…in 循环遍历对象属性时,并不能保证属性的迭代顺序。对象属性的遍历顺序可能因 JavaScript 引擎而异,因此不应依赖于属性的特定顺序。

  • 继承的属性也会被迭代:for…in 循环将遍历对象自身及其原型链上可枚举的属性。如果只希望遍历对象自身的属性,可以使用 object.hasOwnProperty(key) 来过滤继承的属性。

  • 不适用于数组遍历:虽然 for…in 循环可以遍历数组,但它并不是处理数组的最佳选择。由于数组的索引被视为对象的属性,遍历数组时可能会迭代到其他非数值属性。

  • 忽略 Symbol 属性:for…in 循环会忽略对象中的 Symbol 属性。如果需要遍历所有属性,包括 Symbol 属性,可使用 Object.getOwnPropertySymbols() 方法获取 Symbol 属性数组,并进行遍历。


for…of 循环

概述

for…of 循环是一种专门用于遍历可迭代对象的循环语法。与传统的 for 循环或 for…in 循环不同,for…of 循环主要用于访问数据结构中的元素值,而非索引或属性名。它提供了一种简单且易于使用的方式来迭代数组、字符串、Set、Map 等内置可迭代对象。

用法

使用 for…of 循环的关键是了解其基本语法和使用方法。for…of 循环语法如下:

for (variable of iterable) {
   // 在此处执行操作
}

其中,variable 是一个变量,代表当前循环迭代的元素值;iterable 是要迭代的可迭代对象。

接下来,我们通过一些小例子来演示 for…of 循环的用法:

  • 遍历数组:
const arr = [1, 2, 3, 4, 5];

for (let element of arr) {
  console.log(element);
}

我们定义了一个名为 arr 的数组,并使用 for…of 循环遍历数组的每个元素。循环体内的语句console.log(element) 输出了每个元素的值。

  • 遍历字符串:
const str = 'Hello';

for (let char of str) {
  console.log(char);
}

这个例子中,我们定义了一个名为 str 的字符串,并使用 for…of 循环遍历字符串的每个字符。循环体内的语句 console.log(char) 输出了每个字符。

  • 遍历 Set:
const set = new Set([1, 2, 3, 4, 5]);

for (let element of set) {
  console.log(element);
}

这个例子中,我们定义了一个名为 set 的 Set 对象,并使用 for…of 循环遍历 Set 中的每个元素。循环体内的语句 console.log(element) 输出了每个元素的值。

可迭代对象

for…of 循环可以遍历多种内置可迭代对象,包括但不限于:

数组(Array)
字符串(String)
类数组对象(如 arguments 对象)
Set
Map
Generator 对象
TypedArray

需要注意的是,for…of 循环不适用于普通对象(Plain Object),因为它们并非可迭代对象。

对于自定义对象,如果想要使用 for…of 循环进行迭代,需要实现 Iterable 接口,即定义一个 [Symbol.iterator] 方法,使其返回一个具有 next() 方法的迭代器对象。


forEach 方法

概述

forEach 方法是数组对象的一个内置方法,用于迭代数组中的每个元素。它接受一个回调函数作为参数,在遍历数组时会依次调用该函数,并传递当前元素、索引和原数组作为参数。与传统的 for 循环或 for…of 循环不同,forEach 方法主要用于遍历数组,并对每个元素执行特定操作。

用法

使用 forEach 方法的关键是了解其基本语法和使用方法。forEach 方法的语法如下:

array.forEach(function(element, index, array) {
   // 在此处执行操作
});

其中,array 是要遍历的数组;element 是回调函数中表示当前元素的参数;index 是回调函数中表示当前索引的参数;array 是回调函数中表示原数组的参数。

接下来,我们通过一些示例来演示 forEach 方法的用法:

  1. 遍历数组并输出每个元素:
const arr = [1, 2, 3, 4, 5];

arr.forEach(function(element) {
  console.log(element);
});

我们定义了一个名为 arr 的数组,并使用 forEach 方法遍历数组的每个元素。回调函数function(element) 输出了每个元素的值。

  1. 计算数组中每个元素的平方并存储到新数组中:
const arr = [1, 2, 3, 4, 5];
const squaredArr = [];

arr.forEach(function(element) {
  squaredArr.push(element * element);
});

console.log(squaredArr);

这个小例子中,我们定义了一个名为 arr 的数组,并使用 forEach 方法遍历数组的每个元素。在回调函数 function(element) 中,我们将每个元素的平方值推入 squaredArr 数组中,并最终打印 squaredArr

注意事项

在使用 forEach 方法时,需要注意以下几点:

  • 无法使用 break 或 continue 关键字:forEach 方法无法直接使用 break 或 continue 关键字来中断循环或跳过当前迭代。如果需要实现类似的功能,可以使用抛出异常或返回 false 来提前结束迭代。

  • 无法修改原数组:forEach 方法不会返回一个新的数组,也无法修改原数组的长度或内容。如果需要修改原数组,可以使用索引访问或其他数组方法(如 map、filter、reduce 等)。

  • 不支持异步操作:forEach 方法是同步执行的,不支持处理异步操作。如果需要处理异步操作,可以使用其他适合的方法,如 for 循环、for…of 循环、Promise 或 async/await。

reduce()方法

概述

reduce 方法是 JavaScript 数组的一个高阶函数,用于将数组的所有元素聚合为单个结果。它使用一个累加器和一个回调函数来进行聚合操作。

用法

reduce 方法的基本语法如下:

array.reduce(callback, initialValue)

其中,array 是要操作的数组;callback 是用于聚合操作的回调函数;initialValue 是可选的初始值,用作第一次调用回调函数时的累加器的初始值。

回调函数 callback 接受四个参数:accumulator(累加器)、currentValue(当前值)、currentIndex(当前索引)和 array(原始数组)。回调函数会被依次应用于数组的每个元素,从左到右进行聚合操作。
下面通过举例来演示 reduce 方法的用法:

  1. 计算数组元素之和:
const arr = [1, 2, 3, 4, 5];

const sum = arr.reduce(function(accumulator, currentValue) {
  return accumulator + currentValue;
}, 0);

console.log(sum); // 输出:15

上面这个例子里,我们定义了一个名为 arr 的数组,并使用 reduce 方法计算数组所有元素的和。回调函数 function(accumulator, currentValue) 将累加器 accumulator 和当前值 currentValue 相加,并返回新的累加器的值。

  1. 查找数组中的最大值:
const arr = [7, 2, 9, 1, 5];

const max = arr.reduce(function(accumulator, currentValue) {
  return Math.max(accumulator, currentValue);
}, arr[0]);

console.log(max); // 输出:9

此例子中,我们定义了一个名为 arr 的数组,并使用 reduce 方法查找数组中的最大值。回调函数 function(accumulator, currentValue) 使用 Math.max 函数比较累加器 accumulator 和当前值 currentValue,并返回较大的值作为新的累加器的值。初始累加器的值设为 arr[0],即数组的第一个元素。

  1. 数组元素计数和分类:
const arr = ['apple', 'banana', 'apple', 'orange', 'banana'];

const result = arr.reduce(function(accumulator, currentValue) {
  if (!accumulator[currentValue]) {
    accumulator[currentValue] = 1;
  } else {
    accumulator[currentValue]++;
  }
  return accumulator;
}, {});

console.log(result);
// 输出:
// {
//   apple: 2,
//   banana: 2,
//   orange: 1
// }

我们定义了一个名为 arr 的数组,并使用 reduce 方法统计每个元素出现的次数,并将结果存储在一个对象中。回调函数 function(accumulator, currentValue) 判断累加器 accumulator 中是否已存在当前值 currentValue 的计数,如果不存在则初始化为 1,否则增加计数。初始累加器的值通过 {} 创建一个空对象。

注意事项

  • reduce 方法可以接受一个可选的初始值 initialValue,用作第一次调用回调函数时的累加器的初始值。如果未提供初始值,则第一次调用回调函数时,累加器的初始值将为数组的第一个元素。
  • reduce 方法返回的是聚合的最终结果,而不是数组。

对比与选择

接下来我们对遍历常用方法: for 循环for...of 循环forEach 方法map 方法for...in循环reduce 方法。下面对这些方法进行对比和选择:

  1. for 循环:for 循环是最基本的遍历数组的方法,它提供了最大的灵活性,可以执行各种操作。但是需要手动管理索引和循环终止条件,并且代码相对繁琐。
  2. for…of 循环:for…of 循环是 ES6 引入的新语法,用于遍历可迭代对象(包括数组)。它简洁明了,不需要管理索引,而且支持使用 break 和 continue 关键字。然而,无法在循环中修改原数组的元素。
  3. forEach 方法:forEach 方法是一个高阶函数,提供了一种简洁的方式来遍历数组并对每个元素执行操作。它具有良好的可读性和易用性,无需关心索引和循环终止条件,但无法使用 break 或 continue 关键字。此外,forEach 方法是同步执行的,不支持处理异步操作。
  4. map 方法:map 方法可用于遍历数组并返回一个新数组,其中每个元素都经过回调函数的处理。与 forEach 方法不同,map 方法返回一个新数组,不会修改原数组的内容。这在需要对每个元素进行转换或映射的情况下非常有用。
  5. reduce 方法:reduce 方法允许通过迭代将数组的所有元素聚合为一个值。它使用一个累加器和回调函数来执行指定的聚合操作。reduce 方法可用于计算总和、求平均值、查找最大/最小值等。与 forEach 方法不同,reduce 方法返回单个结果而不是数组。

一般来说:

  • 如果只需要遍历数组并处理每个元素,没有返回值的要求,可以使用 forEach 方法,简洁易读。
  • 如果需要在遍历过程中修改原数组的元素,可以使用 for 循环或 map 方法。
  • 如果需要对每个数组元素进行转换或映射,并返回一个新的数组,可以使用 map 方法。
  • 如果需要将数组的所有元素聚合为单个结果,可以使用 reduce 方法。
  • 如果需要同时管理索引和元素,或者需要使用 break 或 continue 关键字来控制循环流程,可以使用 for 循环或 for…of 循环。

关键问题——for…in循环
单独把for...in循环拿出来,是因为它比较特殊

for…in循环用于遍历对象的可枚举属性,而不是数组的元素。它会遍历对象的所有可枚举属性,包括从原型链继承而来的属性。因此,不建议将for…in循环用于遍历数组。

以下是for…in循环的特点和适用场景:

  • for...in循环会遍历对象的可枚举属性,包括字符串类型的键和符号类型的键。
  • 在遍历过程中,循环变量会依次取得对象的每个属性名。可以通过使用该属性名获取对象的属性值。
  • 循环变量可能不按照任何特定顺序遍历对象的属性。
  • for...in循环还会遍历对象从原型链上继承而来的属性,这可能会导致意外的问题。
  • 可以通过使用Object.hasOwnProperty方法来判断当前属性是否为对象自身的属性而非继承来的属性。

由于for…in循环的特性,通常建议在处理数组时使用其他的遍历方式(如for循环、for…of循环、forEach方法、map方法和reduce方法),而将for…in循环用于遍历对象的属性。

在这里插入图片描述


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

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

相关文章

苍穹外卖day09——历史订单模块(用户端)+订单管理模块(管理端)

查询历史订单——需求分析与设计 产品原型 业务规则 分页查询历史订单 可以根据订单状态查询 展示订单数据时,需要展示的数据包括:下单时间、订单状态、订单金额、订单明细(商品名称、图片) 接口设计 查询历史订单——代码开…

抖音seo短视频账号矩阵系统技术开发简述

说明:本开发文档适用于抖音seo源码开发,抖音矩阵系统开发,短视频seo源码开发,短视频矩阵系统源码开发 一、 抖音seo短视频矩阵系统开发包括 抖音seo短视频账号矩阵系统的技术开发主要包括以下几个方面: 1.前端界面设…

线程初见——对速度的追求

文章目录 线程进程线程区别线程之间资源线程库介绍 线程 同一个程序的所有线程共享一份全局内存区域 特例:只包含一个线程的进程 查看线程号:ps -Lf 号 和进程类似,完成并发任务的执行 进程线程区别 区别进程线程信息交换内存未共享&#xf…

cad丢失mfc140u.dll怎么办?找不到mfc140u.dll的解决方法

第一:mfc140u.dll有什么用途? mfc140u.dll是Windows操作系统中的一个动态链接库文件,它是Microsoft Foundation Class (MFC)库的一部分。MFC是 C中的一个框架,用于构建Windows应用程序的用户界面和功能。mfc140u.dll包含了MFC库中…

CAN15765和1939协议

1. 15765协议介绍 简单的来说,15765协议指的是 基于CAN2.0A/B 协议 (也可以叫做ISO11898协议 -链路层) 硬件接口的 应用层 通讯协议, 它用于实现通用的车辆诊断服务。 ISO11898协议参考下图。 参考搜索到的“CAN总线协议讲解…

【MySQL】索引特性

​🌠 作者:阿亮joy. 🎆专栏:《零基础入门MySQL》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录 👉没…

蓝图节点编辑器

打印字符串 第02章 蓝图结构 03 -注释和重新路由_哔哩哔哩_bilibili 第02章 蓝图结构 04 - 变量_哔哩哔哩_bilibili 第03章 蓝图简易门 01 - 箱子碰撞_哔哩哔哩_bilibili 第03章 蓝图简易门 02 - 静态Mesh和箭头_哔哩哔哩_bilibili 第03章 蓝图简易门 03 - 设置相对旋转节点_哔…

流数据湖平台Apache Paimon(三)Flink进阶使用

文章目录 2.9 进阶使用2.9.1 写入性能2.9.2 读取性能2.9.3 多Writer并发写入2.9.4 表管理2.9.5 缩放Bucket 2.10 文件操作理解2.10.1 插入数据2.10.2 删除数据2.10.3 Compaction2.10.4 修改表2.10.5 过期快照2.10.6 Flink 流式写入 2.9 进阶使用 2.9.1 写入性能 Paimon的写入…

c++ 类的特殊成员函数:拷贝构造函数(四)

1. 简介 拷贝构造是一种特殊的构造函数,用于创建一个对象,该对象是从同一类中的另一个对象复制而来的。拷贝构造函数通常采用引用参数来接收要复制的对象,并使用该对象的副本来创建一个新对象。 2. 结构 class MyClass { public:MyClass(c…

一种新的基于区域的在线活动轮廓模型研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

SpringBoot热部署的开启与关闭

1、 开启热部署 &#xff08;1&#xff09;导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId> </dependency>&#xff08;2&#xff09;设置 此时就搞定了。。。 2、…

TCP网络通信编程之网络上传文件

【图片】 【思路解析】 【客户端代码】 import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException;/*** ProjectName: Study* FileName: TCPFileUploadClient* author:HWJ* Data: 2023/7/29 18:44*/ public class TCPFil…

解决在云服务器开放端口号以后telnet还是无法连接的问题

这里用阿里云服务器举例&#xff0c;在安全组开放了对应的TCP端口以后。使用windows的cmd下的telnet命令&#xff0c;还是无法正常连接。 telnet IP地址 端口号解决方法1&#xff1a; 在轻量服务器控制台的防火墙规则中添加放行端口。 阿里云-管理防火墙 如图&#xff0c;开放…

Windows 11 下 OpenFace 2.2.0 的安装

写在前面 最近需要做关于面部的东西&#xff0c;所以需要使用到OpenFace这个工具&#xff0c;本文仅用来记录本人安装过程以供后续复现&#xff0c;如果可以帮助到读者也是非常荣幸。 安装过程 不编译直接使用 这种方法可以直接从官方下载下来编译好的exe以及gui进行使用&a…

1000Wqps生产级IM,怎么架构?

前言 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;很多小伙伴拿高薪&#xff0c;完成架构的升级&#xff0c;进入架构师赛道&#xff0c;打开薪酬天花板。 然后&#xff0c;在架构师的面试过程中&#xff0c;常常会遇到IM架构的问题&#xff1a; 如果要你从0到1做IM架构…

python与深度学习(十):CNN和cifar10二

目录 1. 说明2. cifar10的CNN模型测试2.1 导入相关库2.2 加载数据和模型2.3 设置保存图片的路径2.4 加载图片2.5 图片预处理2.6 对图片进行预测2.7 显示图片 3. 完整代码和显示结果4. 多张图片进行测试的完整代码以及结果 1. 说明 本篇文章是对上篇文章训练的模型进行测试。首…

Flutter 使用texture_rgba_renderer实现桌面端渲染视频

Flutter视频渲染系列 第一章 Android使用Texture渲染视频 第二章 Windows使用Texture渲染视频 第三章 Linux使用Texture渲染视频 第四章 全平台FFICustomPainter渲染视频 第五章 Windows使用Native窗口渲染视频 第六章 桌面端使用texture_rgba_renderer渲染视频&#xff08;本…

MySQL高级篇第3章(用户与权限管理)

文章目录 1、用户管理1.1 登录MySQL服务器1.2 创建用户1.3 修改用户1.4 删除用户1.5 设置当前用户密码1.6 修改其他用户密码1.7 MySQL8密码管理 2、权限管理2.1 全新列表2.2 授予权限的原则2.3 授予权限2.4 查看权限2.5 收回权限 3、权限表3.1 user表3.2 db表3.3 tables_priv表…

ssti总结转载

一、初识SSTI 1、什么是SSTI&#xff1f; SSTI就是服务器端模板注入(Server-Side Template Injection)&#xff0c;实际上也是一种注入漏洞。 可能SSTI对大家而言不是很熟悉&#xff0c;但是相信大家很熟悉SQL注入。实际上这两者的思路都是相同的&#xff0c;因此可以类比来分…

【嵌入式Linux系统开发】——系统移植概述

目录 &#x1f349;&#x1f349;一、什么是嵌入式系统 &#x1f349;&#x1f349;二、嵌入式系统操作 &#x1f349;&#x1f349;三、嵌入式Linux的特点 &#x1f349;&#x1f349;四、嵌入式系统的组成 1、硬件和软件 2、硬件层 3、中间层 4、软件层 5、 功能层与执…