您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

JS中常用的6种数组遍历方法

时间:2023-06-26 14:47:58  来源:  作者:尚硅谷教育

在前端开发当中,我们通常要对后端返回的数据进行一些处理再渲染到页面,而其中常用的就是数组的不同遍历方法,因此熟练掌握这些方法是非常有必要的,而对于初学者来说,这些方法不太容易理解也容易被混淆,今天我们就通过本篇教会大家区别数组的forEach,map,filter,reduce,some,every这6种遍历方法。

一、这些方法的共同语法

除了reduce方法语法略有不同(后面单独讲解),其他五个方法forEach,map,filter,some,every传入的第一个参数语法相同

(1)第一个参数为回调函数:callbackFn(item,index,arr),该函数接收三个参数item,index,arr。

(2)三个参数分别表示:

  • item:当下遍历的数组元素的值;当数组的元素为基本数据类时,item是直接赋值为元素的值;当数组的元素为引用数据类型时,此时item是引用赋值,即该地址值会指向原数组的元素(在map方法里会举例说明)。
  • index:当下遍历的数组元素的索引;
  • arr:表示原数组。

下面我们通过具体讲解这些方法,来说明这些方法的不同之处以及使用场景。

二、forEach和map方法

forEach方法和map方法比较相似,所以我们这里一同讲解。首先我们了解一下这2种方法的基本概念:

(1)forEach方法:没有返回结果,返回值为undefined,本质上等同于 for 循环;

(2)map方法:会返回一个新数组,新数组的元素为原始数组元素调用函数处理的后return返回的值。

在大部分使用场景中,这2种方法都可以获得相同的结果,只是具体操作步骤有所不同,下面我们就以数组的数据类型为基本数据类型和引用数据类型2种情况举例。

2.1 数组数据类型:基本数据类型

假设我们有个数组[1,2,3,4,5],现在我们需要让数组的每个元素乘以2。

(1)使用forEach方法:

let arr = [1,2,3,4,5]

arr.forEach(function(item,index,arr){

arr[index] = item*2

})

console.log(arr) // [2,4,6,8,10]

// 用forEach方法改动原数组的元素,我们让原数组的每个元素变成了之前的2倍

这里我们使用forEach方法直接修改原数组,让原数组的每个元素直接替换为item*2,原数组就改成了我们需要的结果。

(2)使用map方法:

let arr = [1,2,3,4,5]

let newArr = arr.map(function(item,index,arr){

return item*2

})

console.log(newArr) // [2,4,6,8,10]

这里我们用map方法return出的item*2就是最终新数组的每个元素值,此时map方法不会改动原数组。如果不能改动原数组,此时就用map方法。

2.2 数组数据类型:引用数据类型

假设我们有个对象数组,现在需要改动每个对象元素的属性。

(1)使用forEach方法:

let arr = [

{ id: '01001', title: '考研成绩' },

{ id: '01002', title: '中国经济复苏进度条' },

]

arr.forEach(function(item,index,arr){

item.date = "2023-1-1"

})

console.log(arr)

打印结果为:

这里我们使用forEach方法直接修改原数组,为原数组的每个元素都添加了date属性。

(2)使用map方法:

let arr = [

{ id: '01001', title: '考研成绩' },

{ id: '01002', title: '中国经济复苏进度条' },

]

let newArr = arr.map(function(item,index,arr){

item.date = "2023-1-1"

return item

})

console.log("arr",arr)

console.log("newArr",newArr)

打印结果为:

开头我们介绍这些方法的语法时有讲到,item如果是对象是引用数据类型就是引用赋值,所以直接改动item属性也会改动原数组。此时用map返回新数组的意义就不大,直接用forEach就可以实现这种效果。

而当我们需要不改动原数组时,我们先要对数据进行拷贝处理。举例如下:

let arr = [

{ id: '01001', title: '考研成绩' },

{ id: '01002', title: '中国经济复苏进度条' },

]

let newArr = arr.map(function(item,index,arr){

item = {...item} // 这里我们多了一步拷贝处理

item.date = "2023-1-1"

return item

})

console.log("arr",arr)

console.log("newArr",newArr)

打印结果如下:

此时我们可以看到原数组并没有被改动,新数组的是我们想要的结果。

另外,map方法因为会返回新数组,所以可以与reduce、filter等方法组合使用,以便在一条语句中执行多个操作,如下例所示:

let arr = [

{ id: '01001', title: '考研成绩', isHot: true },

{ id: '01002', title: '中国经济复苏进度条', isHot: false },

]

// 用map方法给数据加上日期属性

let result = arr.map((item) => {

item = {...item}

item.date = '2023-01-01'

return item

// map方法后紧接着使用filter方法过滤数据

}).filter((item) => {

return item.isHot === true

})

console.log(result)

上面代码的打印结果如下,此时数据既添加了date属性,又过滤出了isHot为true的数据。

三、filter方法

3.1 概念

定义:遍历数组并返回一个新的数组,新数组中的元素是通过检查指定数组中满足条件的所有元素。(即过滤数组并返回新数组,不会改变原数组)

3.2 举例

注意:传入的函数里必填return,因为会根据return的值为false或true来过滤数据。

(1)直接return布尔值,为true则元素值放入数组中,为false的就被过滤掉。

let arr = [

{ id: '01001', title: '考研成绩', isHot: true },

{ id: '01002', title: '中国经济复苏进度条', isHot: false },

]

let result = arr.filter((item) => {

return item.isHot

})

console.log(result) // [{ id: '01001', title: '考研成绩', isHot: true }]

// 看打印结果可以发现isHot为false的对象数据就被过滤掉了

(2)return非布尔值时,也会通过将数据隐式转化为布尔值来过滤数组。

let arr = [1,undefined,null,3,0,"",NaN]

let result = arr.filter((item) => {

return item

})

console.log(result) // [1,3]

// 将item的值转化为布尔值后,为false的元素就被过滤掉了,留下的为true的

(3)与其他方法结合使用:

这里先用一个小例子帮大家回忆一下数组的indexOf()方法的用法:用于返回某个指定的值在数组中首次出现的索引值,如果没有找到匹配的元素则返回 -1。

let arr = [1, 2, 3, 4, 5];

let index = arr.indexOf(2);

// 在数组中查找是否有2这个元素

console.log(index) //打印结果是1,表示2和数组中索引为1的元素的值匹配

①与indexOf()方法组合使用进行数组去重:

let arr = [1,1,2,4,5,6,5,5,6]

let newArr = arr.filter((item,index)=>{

return arr.indexOf(item) === index

// 因为indexOf始终返回第一个符合条件的元素的索引

// 数组中重复出现的数值就不可能满足全等判断,就会被过滤掉

})

console.log(newArr) // [1,2,4,5,6]

②还有与map方法一起使用的例子,map方法介绍中已举例,这里就不重复说明了。

四、reduce方法

4.1 概念

(1)定义:遍历数组,并构建返回一个最终的值。

(2)语法:

array.reduce(function(previous,current,index,arr),initValue);

(3)参数说明:

①不传第二参数initValue时,我们以一个计算数组元素相加之和的例子说明:

let arr = [1,3,5,7]

let result = arr.reduce((previous,current)=>{

console.log('previous:',previous, ' current:',current)

return previous + current

})

console.log('result:',result)

打印结果为:

我们可以看到:

(a)传入的箭头函数执行了数组长度-1次,也就是3次;

(b)回调函数多次调用:

第一次调用时,previous表示就是数组的第一个元素的值1,current是数组第二个元素的值3;

第二次调用时,previous表示的是上次调用时return出来的值也就是1+3为4,current是数组第三个元素的值5;

第三次调用时,previous同样表示的是上次调用返回的值也就是4+5为9,current表示数组第四个元素的值7。

(c)result的值就是最后一次计算9+7的结果值16。

②传入第二参数initValue时,我们以一个获得新数组的每个元素是原数组每个元素累计相加之和的例子说明:

let arr = [1,3,5,7]

let sum = 0

let result = arr.reduce((previous,current)=>{

console.log(previous, 'current:', current)

previous.push(sum + current)

sum += current

return previous

}, [])

console.log('result:', result)

打印结果为:

我们可以看到:

(a)传入的箭头函数执行了arr数组长度一样的次数,也就是4次;

(b)previous:箭头函数第一次调用时,表示的是传入的初始值initValue,也就是空数组,后面表示的是上次return出来的值;current:始终表示的是数组arr的每个元素的值;

(c)result同样表示最后一次箭头函数调用return返回的结果。

4.2 举例

上面我们举了2个简单例子区分reduce方法传入1个参数和2个参数的区别,下面我以一个计算购物车选中产品数量的例子来说明项目中reduce的具体应用场景。

目前购物车一共有3个产品,其中选中了2种产品,并计算选中的总价为22393,我们可以通过reduce方法计算①②这个2个值。

// arr表示购物车里所有产品数组,其中用不到的数据就省略了

let arr = [

{

id:12334,

isChecked:1, // 1表示购物车选中了这个产品

cartPrice:5999, // 表示产品单价5999

skuNum:1, // 表示购物车产品数量为1

skuName:"小米10 至尊纪念版 双模5G 骁龙865 120W快充 8GB+128GB 陶瓷黑 游戏手机",

},

{

id:12375,

isChecked:0, // 0表示购物车没有选中这个产品

cartPrice:2323, // 表示产品单价为2323

skuNum:1, // 表示购物车产品数量为1

skuName:"华为P40 5G全网通智能手机 支持鸿蒙HarmonyOS 零度白 8G+128G",

},

{

id:12376,

isChecked:1, // 1表示购物车选中了这个产品

cartPrice:8197, // 表示产品单价为8197

skuNum:1, // 表示购物车产品数量为1

skuName:"Apple iphone 12 (A2404) 64GB 黑色 支持移动联通电信5G 双卡双待手机",

},

]

因为每个产品对象的isChecked属性1就表示选中了,0表示没有选中,因此我们可以通过累计相加这个值来计算购物车选择的产品数:

// 计算购物车选中产品数

let num = arr.reduce((previous,current)=>{

return previous + current.isChecked

// previous初始值是传入的第二个参数0,current表示数组的当前遍历到的对象

},0)

// 通过累计相加所有产品的isChecked的属性值,获得选中的产品数量num为2

计算选中产品总价格,我们也是通过reduce方法累计计算:

// 计算购物车选中产品总价格

let price = arr.reduce((previous,current)=>{

return previous + current.isChecked * current.cartPrice * current.skuNum

// 选中的产品的数量和价格的乘积累计相加

},0)

// 最终的price的值就是选中产品总价

通过上面的例子我们可以看到这种要累计计算处理数据的情况,使用reduce方法是比较方便的操作。

五、some和every方法

因为some()方法和every()方法比较简单,因为比较相似所以这里也是一起讲解。

概念及举例

(1)some()方法用于检测数组中的元素是否满足return的判断条件,如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测;如果没有满足条件的元素,则返回false。

// some方法只要有一个元素符合return的条件就返回true,后面元素就不会再执行判断

let arr = [2,3,4,6]

let result = arr.some((item)=>{

return item % 2 === 1 // 判断数组的每个元素是否除以2能余1

})

console.log(result) // 因为第二个元素3符合,所以结果为true

(2)every()方法用于检测数组中的元素是否都满足return的判断条件,只要有一个不符合就会返回false,都符合才返回true。

// every方法要求所有元素符合return的判断条件才返回true,不然就返回false

let arr = [2,3,4,6]

let result = arr.every((item)=>{

return item % 2 === 0 // 判断数组的每个元素是否都能被2整除

})

console.log(result) // 因为第二个元素3不符合条件,所以结果为false

总结

(1)forEach方法没有返回值,一般用于直接修改原数组;

(2)map方法会返回新的数组,在处理元素为引用数据类型的数组时可以通过数据的拷贝不修改原数组(拷贝的方法我们会在下回和大家做专门的讲解),并且可以结合其他方法执行更多层的操作;

(3)filter()方法用于过滤数组,返回的结果就是过滤后的新数组;

(4)reduce()方法在一般需要对数组元素的数据进行一些运算处理时使用,返回的值就是最终的结果;

(5)some()方法用于判断数组中是否有满足条件的元素,返回结果是布尔值,只要有一个符合就是true;

(6)every()方法用于判断数组中的元素是否都符合判断条件,返回结果是布尔值,都符合才会返回true。



Tags:JS   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
又出新JS运行时了!JS运行时大盘点
Node.js是基于Google V8引擎的JavaScript运行时,以非阻塞I/O和事件驱动架构为特色,实现全栈开发。它跨平台且拥有丰富的生态系统,但也面临安全性、TypeScript支持和性能等挑战...【详细内容】
2024-03-21  Search: JS  点击:(25)  评论:(0)  加入收藏
GitHub顶流"Web OS"——运行于浏览器的桌面操作系统、用户超100万、原生jQuery和JS编写
Puter 是近日在 GitHub 上最受欢迎的一款开源项目,正式开源还没到一周 ——star 数就已接近 7k。作者表示这个项目已开发 3 年,并获得了超过 100 万用户。根据介绍,P...【详细内容】
2024-03-10  Search: JS  点击:(17)  评论:(0)  加入收藏
前端开始“锈化”?Vue团队开源JS打包工具:基于Rust、速度极快、尤雨溪主导
Vue 团队已正式开源Rolldown —— 基于 Rust 的 JavaScrip 打包工具。Rolldown 是使用 Rust 开发的 Rollup 替代品,它提供与 Rollup 兼容的应用程序接口和插件接口...【详细内容】
2024-03-09  Search: JS  点击:(11)  评论:(0)  加入收藏
如何在Rust中操作JSON,你学会了吗?
sonic-rs ​还具有一些额外的方法来进行惰性评估和提高速度。例如,如果我们想要一个 JSON​ 字符串文字,我们可以在反序列化时使用 LazyValue​ 类型将其转换为一个仍然带有斜...【详细内容】
2024-02-27  Search: JS  点击:(47)  评论:(0)  加入收藏
JS小知识,使用这6个小技巧,避免过多的使用 if 语句
最近在重构我的代码时,我注意到早期的代码使用了太多的 if 语句,达到了我以前从未见过的程度。这就是为什么我认为分享这些可以帮助我们避免使用过多 if 语句的简单技巧很重要...【详细内容】
2024-01-30  Search: JS  点击:(56)  评论:(0)  加入收藏
花 15 分钟把 Express.js 搞明白,全栈没有那么难
Express 是老牌的 Node.js 框架,以简单和轻量著称,几行代码就可以启动一个 HTTP 服务器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都与 Express 息息相关。Express 框...【详细内容】
2024-01-16  Search: JS  点击:(88)  评论:(0)  加入收藏
JS 中如何克隆对象?你学会了吗?
大家好,这里是大家的林语冰。JS 中如何克隆对象?此问题看似简单,实际十分复杂。假设我们需要获取下述对象的拷贝。const cat = { name: '薛定谔', girlFriends: { na...【详细内容】
2024-01-05  Search: JS  点击:(104)  评论:(0)  加入收藏
理解 Node.js 中的事件循环
你已经使用 Node.js 一段时间了,构建了一些应用程序,尝试了不同的模块,甚至对异步编程感到很舒适。但是有些事情一直在困扰着你——事件循环(Event Loop)。如果你像我...【详细内容】
2024-01-05  Search: JS  点击:(113)  评论:(0)  加入收藏
彻底搞懂 JS 类型转换
1. 什么是类型转换?Javascript 是一种弱类型语言,这意味着变量是没有明确类型的,而是由 JavaScript 引擎在编译时隐式完成。类型转换就是将一种数据类型转换为另一种数据类型,例...【详细内容】
2024-01-03  Search: JS  点击:(104)  评论:(0)  加入收藏
.NET配置文件大揭秘:轻松读取JSON、XML、INI和环境变量
概述:.NET中的IConfiguration接口提供了一种多源读取配置信息的灵活机制,包括JSON、XML、INI文件和环境变量。通过示例,清晰演示了从这些不同源中读取配置的方法,使配置获取变得...【详细内容】
2023-12-28  Search: JS  点击:(92)  评论:(0)  加入收藏
▌简易百科推荐
17 个你需要知道的 JavaScript 优化技巧
你可能一直在使用JavaScript搞开发,但很多时候你可能对它提供的最新功能并不感冒,尽管这些功能在无需编写额外代码的情况下就可以解决你的问题。作为前端开发人员,我们必须了解...【详细内容】
2024-04-03  前端新世界  微信公众号  Tags:JavaScript   点击:(5)  评论:(0)  加入收藏
你不可不知的 15 个 JavaScript 小贴士
在掌握如何编写JavaScript代码之后,那么就进阶到实践——如何真正地解决问题。我们需要更改JS代码使其更简单、更易于阅读,因为这样的程序更易于团队成员之间紧密协...【详细内容】
2024-03-21  前端新世界  微信公众号  Tags:JavaScript   点击:(27)  评论:(0)  加入收藏
又出新JS运行时了!JS运行时大盘点
Node.js是基于Google V8引擎的JavaScript运行时,以非阻塞I/O和事件驱动架构为特色,实现全栈开发。它跨平台且拥有丰富的生态系统,但也面临安全性、TypeScript支持和性能等挑战...【详细内容】
2024-03-21  前端充电宝  微信公众号  Tags:JS   点击:(25)  评论:(0)  加入收藏
构建一个通用灵活的JavaScript插件系统?看完你也会!
在软件开发中,插件系统为应用程序提供了巨大的灵活性和可扩展性。它们允许开发者在不修改核心代码的情况下扩展和定制应用程序的功能。本文将详细介绍如何构建一个灵活的Java...【详细内容】
2024-03-20  前端历险记  微信公众号  Tags:JavaScript   点击:(20)  评论:(0)  加入收藏
对JavaScript代码压缩有什么好处?
对JavaScript代码进行压缩主要带来以下好处: 减小文件大小:通过移除代码中的空白符、换行符、注释,以及缩短变量名等方式,可以显著减小JavaScript文件的大小。这有助于减少网页...【详细内容】
2024-03-13  WangLiwen    Tags:JavaScript   点击:(2)  评论:(0)  加入收藏
跨端轻量JavaScript引擎的实现与探索
一、JavaScript 1.JavaScript语言JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。ECMAScript发展史: 2.JavaScript...【详细内容】
2024-03-12  京东云开发者    Tags:JavaScript   点击:(2)  评论:(0)  加入收藏
面向AI工程的五大JavaScript工具
令许多人惊讶的是,一向在Web开发领域中大放异彩的JavaScript在开发使用大语言模型(LLM)的应用程序方面同样大有价值。我们在本文中将介绍面向AI工程的五大工具,并为希望将LLM...【详细内容】
2024-02-06    51CTO  Tags:JavaScript   点击:(53)  评论:(0)  加入收藏
JS小知识,使用这6个小技巧,避免过多的使用 if 语句
最近在重构我的代码时,我注意到早期的代码使用了太多的 if 语句,达到了我以前从未见过的程度。这就是为什么我认为分享这些可以帮助我们避免使用过多 if 语句的简单技巧很重要...【详细内容】
2024-01-30  前端达人  今日头条  Tags:JS   点击:(56)  评论:(0)  加入收藏
18个JavaScript技巧:编写简洁高效的代码
本文翻译自 18 JavaScript Tips : You Should Know for Clean and Efficient Code,作者:Shefali, 略有删改。在这篇文章中,我将分享18个JavaScript技巧,以及一些你应该知道的示例...【详细内容】
2024-01-30  南城大前端  微信公众号  Tags:JavaScript   点击:(67)  评论:(0)  加入收藏
使用 JavaScript 清理我的 200GB iCloud,有了一个意外发现!
本文作者在综合成本因素之下,决定用 Java 脚本来清理一下自己的 iCloud,结果却有了一个意外发现,即在 iCloud 中上传同一个视频和删除此视频之后,iCloud 的空间并不一致,这到底是...【详细内容】
2024-01-11    CSDN  Tags:JavaScript   点击:(99)  评论:(0)  加入收藏
站内最新
站内热门
站内头条