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

在这里插入图片描述

😊博主:小猫娃来啦
😊文章核心: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循环用于遍历对象的属性。

在这里插入图片描述


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用LangChain开源框架实现知识机器人

前言 Large Language Models (LLMs)在2020年OpenAI 的 GPT-3 的发布而进入世界舞台 。从那时起,他们稳步增长进入公众视野。 众所周知 OpenAI 的 API 无法联网,所以大家如果想通过它的API实现联网搜索并给出回答、总结 PDF 文档、基于某个 Youtube 视频…

[nlp] TF-IDF算法介绍

(1)TF是词频(Term Frequency) 词频是文档中词出现的概率。 (2) IDF是逆向文件频率(Inverse Document Frequency) 词条出现率越低,IDF越大。

Dooring-Saas低代码技术详解

hello, 大家好, 我是徐小夕, 今天和大家分享一下基于 H5-Dooring零代码 开发的全新零代码搭建平台 Dooring-Saas 的技术架构和设计实现思路. 背景介绍 3年前我上线了第一版自研零代码引擎 H5-Dooring, 至今已迭代了 300 多个版本, 主要目的是快速且批量化的生产业务/营销过程中…

红黑树解密:为什么根节点必须是黑色,两个红色节点不能挨着?

红黑树解密:为什么根节点必须是黑色,两个红色节点不能挨着? 博主简介一、引言1.1、红黑树是什么及其特点1.2、根节点为黑色和红色节点不连续的性质介绍 二、为何根节点必须是黑色?三、为何两个红色节点不能挨着?总结 博…

RNN架构解析——LSTM模型

目录 LSTMLSTM内部结构图 Bi-LSTM实现 优点和缺点 LSTM LSTM内部结构图 Bi-LSTM 实现 优点和缺点

Windows系统如何修改文件日期属性

winr键,输入powershell,在弹出的命令窗口输入命令,案例如下: file_address E:\_OrderingProject\\PIC1101\ldv1s_0830_ec_result.tiftime_change "07/12/2022 20:42:23" 修改文件创建时间:creationtime $(Get-Item fi…

STL 关于vector的细节,vector模拟实现【C++】

文章目录 vector成员变量默认成员函数构造函数拷贝构造赋值运算符重载函数析构函数 迭代器beginend size和capacityresizereserve[ ]push_backpop_backinserteraseswap vector成员变量 _start指向容器的头,_finish指向容器当中有效数据的下一个位置,_end…

Python零基础入门(九)——函数,类和对象

系列文章目录 个人简介:机电专业在读研究生,CSDN内容合伙人,博主个人首页 Python入门专栏:《Python入门》欢迎阅读,一起进步!🌟🌟🌟 码字不易,如果觉得文章不…

❤️创意网页:萌翻少女心的果冻泡泡 - 创造生动有趣的视觉效果

✨博主:命运之光 🌸专栏:Python星辰秘典 🐳专栏:web开发(简单好用又好看) ❤️专栏:Java经典程序设计 ☀️博主的其他文章:点击进入博主的主页 前言:欢迎踏入…

【UE4】局域网多人联机 Demo

效果 亲测可以打包后在两个电脑上联机运行(前提是在同一个局域网内,互相能ping通) 步骤 1. 首先新建一个第三人称角色模板工程 2. 在多玩家选项中,设置玩家数量为2 选择在新建编辑器窗口中运行 3. 新建一个父类为Character的蓝…

【1.1】Java微服务:初识微服务

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。 🍎个人主页:Meteors.的博客 💞当前专栏: 微服务 ✨特色专栏: 知识分享 &#x…

大数据Flink(五十三):Flink流处理特性、发展历史以及Flink的优势

文章目录 Flink流处理特性、发展历史以及Flink的优势 一、Flink流处理特性 二、发展历史

数据结构入门指南:链表(新手避坑指南)

目录 前言 1.链表 1.1链表的概念 1.2链表的分类 1.2.1单向或双向 1.2.2.带头或者不带头 1.2.33. 循环或者非循环 1.3链表的实现 定义链表 总结 前言 前边我们学习了顺序表,顺序表是数据结构中最简单的一种线性数据结构,今天我们来学习链表&#x…

基于RK3588+AI的边缘计算算法方案:智慧园区、智慧社区、智慧物流

RK3588 AI 边缘计算主板规格书简介 关于本文档 本文档详细介绍了基于Rockchip RK3588芯片的AI边缘计算主板外形、尺寸、技术规格,以及详细的硬件接口设计参考说明,使客户可以快速将RK3588边缘计算主板应用于工业互联网、智慧城市、智慧安防、智慧交通&am…

联想拯救者如何开启独显直连

不同机型有不同的切换方式,下面就分别给大家讲一下: 显卡模式切换方式一: 打开联想电脑管家,选择游戏模式,在左侧菜单栏选择显卡模式,然后就能看到显卡的输出模式了,默认是混合模式&#xff0c…

MDK5__配色方案的修改

一、必要的知识 与MDK主题相关的文件有两个,在X:\Keil_v5\UV4路径下: global.propglobal.prop.def其中global.prop.def是系统默认的主题配置 如果修改过字体等,系统会生成一个global.prop。 二、修改的步骤 1、打开工程 菜单 Edit 下 Con…

【JavaEE】博客系统前后端交互

目录 一、准备工作 二、数据库的表设计 三、封装JDBC数据库操作 1、创建数据表对应的实体类 2、封装增删改查操作 四、前后端交互逻辑的实现 1、博客列表页 1.1、展示博客列表 1.2、博客详情页 1.3、登录页面 1.4、强制要求用户登录,检查用户的登录状态 …

【JVM】详解JVM的五大内存模型、可能出现的异常以及堆栈引用易错点

文章目录 1、堆(线程共享)2、方法区(线程共享)3、虚拟机栈(线程私有)4、本地方法栈(线程私有)5、程序计数器(线程私有)6、易错点 源自:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明 1、堆(线程…

使用克拉默法则进行三点定圆(二维)

目录 1.二维圆2.python代码3.计算结果 本文由CSDN点云侠原创,爬虫网站请自重。 1.二维圆 已知不共线的三个点,设其坐标为 ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​)、 ( x 2 , y 2 ) (x_2,y_2) (x2​,y2​)、 ( x 3 , y 3 ) (x_3,y_3) (x3​,y3​)&#xf…

Ubuntu-文件和目录相关命令一

🔮linux的文件系统结构 ⛳目录结构及目录路径 🧩文件系统层次结构标准FHS Filesystem Hierarchy Standard(文件系统层次结构标准) Linux是开源的软件,各Linux发行机构都可以按照自己的需求对文件系统进行裁剪,所以众多…