JS中循环遍历数组的几种常用方式总结

在这里插入图片描述

第一种:for循环,也是最常见的

最简单的一种,也是使用频率最高的一种,虽然性能不弱,但仍有优化空间

const arr = [11, 22, 33, 44, 55, 66, 77, 88];
for (let i = 0; i < arr.length; i++) {
      console.log(arr[i]);
    }

打印结果:
在这里插入图片描述

第二种:优化版for循环

const arr = [11, 22, 33, 44, 55, 66, 77, 88];
let len = arr.length
for (let i = 0; i < len; i++) {
      console.log(arr[i]);
    }

简要说明:使用临时变量,将长度缓存起来,避免重复计算数组长度,当数组较大时优化效果才会比较明显
缺点:不能在for循环中操作list的大小,比如除去或新加一个元素。
这种方法基本上是所有循环遍历方法中性能最高的一种

第三种:forEach()

在这里插入图片描述

1.)forEach() 遍历普通数组

const arr = [11, 22, 33, 44, 55, 66, 77, 88];
arr.forEach(item => {
      //forEach循环
      console.log(item);
    });

打印结果:
在这里插入图片描述

2.)forEach() 遍历对象类型数组

const arrObj = [
      {
        id: 1,
        name: "张三"
      },
      {
        id: 2,
        name: "李四"
      },
      {
        id: 3,
        name: "王五"
      }
    ];
arrObj.forEach(item => {
   console.log(item.id + "-------" + item.name);
});

打印结果:
在这里插入图片描述

简要说明: 数组自带的foreach循环,使用频率较高,实际上性能比普通for循环弱。原因如下:

一般情况下,普通的 for 循环确实比 forEach 循环有更好的性能,这是因为 forEach 本质上是一个函数调用的过程,而函数调用会带来额外的开销。
具体来说,forEach 循环在每次迭代时都需要执行一次回调函数,并且要对回调函数的执行上下文进行绑定,这样就需要创建和销毁大量的函数堆栈,导致额外的系统开销。而普通的 for 循环则不需要执行函数调用操作,在每次迭代中直接访问元素,极大地提高了代码的执行速度。

使用 forEach 时需要注意几个点:

1)其实对于 forEach 方法,它本身是无法通过 break 或者 return 来中途停止循环的。forEach 方法会遍历数组的每个元素,并对每个元素执行提供的回调函数。无论回调函数中使用了 return 还是 break,都无法停止或跳出整个循环。
中断方法:

  • 使用 try/catch 监视代码块,在需要中断的地方抛出异常。
  • 官方推荐方法(替换方法):用 everysome 代替 forEach 函数。every再碰到 return false 时候,终止循环;some在碰到return true时候,终止循环。

2)forEach 中使用 await 异步代码会导致 forEach 并不能保证按顺序执行。可以改成使用for…of,因为for…of使用迭代器去遍历,会按照迭代器对象定义的顺序,从前往后依次遍历。

针对第二点我们看下面的代码示例:

async function test() {
	let arr = [4, 2, 1]
	arr.forEach(async item => {
		const res = await handle(item)
		console.log(res)
	})
	console.log('结束')
}

function handle(x) {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve(x)
		}, 1000 * x)
	})
}

test()

我们期望的结果是:

4 
2 
1
结束

但实际上会输出:

结束
1
2
4

具体原因

因为 forEach 底层实现是拿过来直接执行了,这就导致它无法保证异步任务的执行顺序。比如后面的任务用时短,那么就又可能抢在前面的任务之前执行。

解决方案
其实也很简单, 我们利用for...of就能轻松解决。

async function test() {
  let arr = [4, 2, 1]
  for(const item of arr) {
	const res = await handle(item)
	console.log(res)
  }
	console.log('结束')
}

第四种:map()

定义和用法

1. map即是 “映射”的意思 ,原数组被“映射”成对应新数组
2. map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
3. map() 不会改变原始数组。
4. map() 不会对空数组进行检测。

5. map支持return

在这里插入图片描述
在这里插入图片描述

 const arr = [11, 22, 33, 44, 55, 66, 77, 88];
 var newArr = arr.map((value, index) => {
      console.log(value + "----" + index);
      return value * 10;
    });
 console.log(newArr);

打印结果:
在这里插入图片描述
简要说明: 这种方式也是用的比较广泛的,虽然用起来比较优雅,但实际效率还比不上foreach

forEach()和map()区别:
两者都是用来遍历数组的。

返回值:

  1. forEach() 方法没有返回值(或者说返回 undefined),它只是对数组的每个元素执行指定的回调函数。
  2. map() 方法返回一个新的数组,该数组包含对原数组每个元素执行回调函数后的结果。

原数组的改变:

  1. forEach() 方法不会改变原始数组。如果在 forEach() 的回调函数中修改了数组的元素,那么这些修改只是针对当前循环的元素有效,不会改变原数组
  2. map() 方法不会改变原始数组,而是返回一个新的数组,该数组由原数组经过回调函数操作后的结果组成。

支持链式调用:
foreach不支持链式调用,而map支持链式调用,可以继续对返回的新数组进行操作。

 const array3 = [1, 2, 3, 4, 5];

 const doubledSum = array3
   .map((element) => element * 2)
   .reduce((accumulator, currentValue) => accumulator + currentValue, 0);
   
 console.log(doubledSum); // 输出: 30

面试:问js的forEach和map的区别

第五种:filter遍历

定义和用法

filter用于对数组进行过滤。
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
filter() 不会对空数组进行检测;不会改变原始数组

语法
array.filter(function(currentValue,index,arr), thisValue)

在这里插入图片描述

let arr = [56, 15, 48, 3, 7];

let newArr = arr.filter(function (value, index, array) {
    return value % 2 === 0;
});

console.log(newArr)
// [56, 48]

第六种:for…of 方法

作为ES6新增的循环方法,个人觉得相当好用,而且方便。这个方法避开了for-in循环的所有缺陷。而且,它可以正确响应break、continue和return语句。

//循环数组
let arr = ['123','qwewq','sfds'];
for(let item of arr){
    console.log(item);    //item指的的就是数组每一项的值。不是索引。
}
//输出
//'123'
//'qwewq'
//'sfds'

for-of循环支持数组、字符串、Set、Map 等。但是for of也有一个致命伤,就像例子看到的,没有索引。对,这是优点也是缺点。遍历数组对象,直接就是item.属性(或者item[属性]),而不用像for循环那样arr[index].属性(arrindex)。但是你有的时候真的就得用到index。不好意思,只能把数组转成Map()。但我觉得真的需要用到index,还是换成forEach吧。

简要说明: 这种方式是es6里面用到的,性能要好于forin,但仍然比不上普通for循环

第七种:for…in 方法

for in循环是用来遍历对象的。要知道JavaScript对象的所有属性都是字符串,不过属性对应的值可以是任意数据类型。(注意:遍历时不仅能读取对象自身上面的成员属性,也能遍历出对象的原型属性)

语法
let obj = {a:1, b:2, c:3};
for (let prop in obj) {    //prop指对象的属性名
console.log(prop, obj[prop]);
}
// 输出:
// a,1
// b,2
// c,3

for in同样可以用来循环数组,但是不推荐这么做。由于Array也是对象,而它的每个元素的索引被视为对象的属性,因此,for in循环可以直接循环出Array的索引,但得到的是String而不是Number,所以一旦你想用这个index去进行计算,就会出错。而且因为会遍历原型属性,所以可能得出的结果不会是你想要的(具体细节不多说,需要了解的自己查询,反正很多坑)。虽然可以用hasOwnProperty()方法避免这个缺陷,但是何必呢,循环方法那么多,换一个就是了。

for (var index in myArray) { // 不推荐这样
console.log(myArray[index]);
}

为什么用for … in?
在这里插入图片描述
简要说明: 这个循环很多人爱用,但实际上,经分析测试,在众多的循环遍历方式中
它的效率是最低的

关于for …of 和 for …in 区别

for of 和 for in 是两种不同的循环语句,用于遍历可迭代对象枚举对象的属性,它们的区别如下:

1)遍历的对象类型不同

  • for of 用于遍历可迭代对象,如数组、字符串、Set、Map等;不会遍历原型链。
  • for in 主要遍历对象,不适用遍历数组;会遍历对象的整个原型链,性能差一些。

2)遍历获取的内容不同

  • for of 遍历获取的是对象的键值
  • for in 遍历获取的是对象的键名(属性名)。

3)遍历顺序不同

  • for of 按照迭代器对象定义的顺序,从前往后依次遍历。
  • for in 遍历对象属性名时,顺序不确定,可能是随机的。(这也是不推荐用在数组上的原因之一)

4)可以使用的对象类型不同

  • for of 适用于可迭代对象,如数组、字符串、Set、Map等;
  • for in 适用于所有对象,包括普通对象、数组、字符串等。

注意:普通对象用 for of 遍历会报错。如果是类数组对象的话可以用Array.from() 转成数组再遍历。

  let forObject = Array.from({ 0: 'one', 1: 'two', 2: 'three', length: 3 })
  for (let item of forObject) {
    console.log(item, 'item')
  }

第八种:find方法

  • 遍历数组,找到第一个符合条件的项,并返回该项;不会继续遍历数组;否则返回undefined
  • 不会改变数组
[1,4,-5,10].find((n) => n < 0 )
//-5

上面代码找出数组中第一个小于0的成员

[1,5,10,15].find(function(value,index,arr){
 return value > 9
})
//10

上面代码中,find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。

第九种:findIndex方法

  • 遍历数组找到第一个符合条件的项,并返回该项的索引值;不会继续遍历数组;否则返回-1。
  • 不会改变数组
[1,5,10,15].findIndex(function(value,index,arr){
 return value > 9
})
//2

findIndex() 当中的回调函数也是接收三个参数,与find() 相同。
在这里插入图片描述
在这里插入图片描述

第十种:Array.some() 方法

1)如果有一个元素满足条件,则表达式返回true,剩余的元素不会再执行检测。
2)如果没有满足条件的元素,则返回false。
3)返回值是布尔值

注意:

1) some() 不会对空数组进行检测。
2) some() 不会改变原始数组。

 var ages = [3, 18, 17, 16]
 var checkoutVal = function checkout (age) {
   console.log(age >= 18) // false true  有一个满足条件的会停止检测剩余的元素
   return age >= 18
 }
 console.log(ages.some(checkoutVal)) // true
let someArr = [2,3,4];
let someResult = someArr.some((item, index)=>{
  return item > 3
});
console.log(someResult);
// 结果为: true

第十一种:Array.every() 方法 (所有的,每一个)

1)如果数组中有一个元素不满足,则整个表达式返回false;且剩余的元素不会再进行检测
2)如果所有元素都满足条件,则返回true
3)返回值是布尔值

注意:

1) every() 不会对空数组进行检测。
2) every() 不会改变原始数组。

  var ages = [3, 18, 17, 16]
  const fn = (currentValue) => currentValue < 40
  console.log(ages.every(fn)) // true  值全都符合函数条件
let everyArr = [2,3,4];
let everyResult = everyArr.every((item, index)=>{
  return item > 0
});
console.log(everyResult);
// 结果为: true

Array.some() 和Array.every() 的区别???

在这里插入图片描述

第十二种:reduce() 方法

reduce() 方法接受一个回调函数和一个可选的初始值作为参数,对数组中的每个元素依次调用回调函数,并将上一次调用的结果传递给下一次调用,最终返回一个累积的结果。

array.reduce(callback, initialValue)
  • 其中,callback 是一个函数,它可以接受四个参数:accumulator(累加器)、currentValue(当前值)、currentIndex(当前索引)和 array(当前数组)。 initialValue 是可选的初始值,
  • 如果提供了初始值,则作为第一次调用回调函数时的 accumulator 值;
  • 如果没有提供初始值,则使用数组的第一个元素作为初始值,并从第二个元素开始调用回调函数。

使用案例:

// reducer
let reduceArr = [0,1,2,3,4]
let reduceResult = reduceArr.reduce((a, b)=>{
  return a + b;
});
console.log(reduceResult);
// 结果: 10

上述列举了几种方式都有一一做过对比分析,基本上可以得出的结论是:
普通for循环才是最优雅的,优化后的for循环最快

注意:
数组方法无法中途停止循环,所以都不可以使用break和continue;
for循环之类的不可以return,但是能正常使用break和continue;

  • 63
    点赞
  • 253
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
JavaScript遍历数组有多种方法。其常用的方法包括forEach、map、for循环、for of、for in、filter和find。 1. 使用forEach方法进行遍历。forEach方法接受一个回调函数作为参数,该函数在遍历数组的每个元素时被调用。可以使用item参数来访问当前遍历到的元素,使用index参数来访问元素的索引,使用self参数来访问数组本身。例如: arr.forEach(function(item, index, self) { console.log(item); }); 这段代码会打印出数组arr的每个元素。 2. 使用map方法进行遍历和映射。map方法也接受一个回调函数作为参数,该函数在遍历数组的每个元素时被调用,并返回一个新的数组。可以使用item参数来访问当前遍历到的元素。例如: let newArr = arr.map(item => { return item * 2; }); 这段代码会将数组arr每个元素都乘以2,并将结果保存在新数组newArr。 3. 使用for循环进行遍历。可以使用临时变量将数组的长度缓存起来,以避免重复获取数组长度。例如: for (var i = 0; i < arr.length; i++) { console.log(arr[i]); } 这段代码会按顺序遍历数组arr的每个元素,并打印出来。 4. 使用for of循环进行遍历。for of循环可以直接遍历数组的每个元素。例如: for (var item of arr) { console.log(item); } 这段代码会按顺序遍历数组arr的每个元素,并打印出来。 5. 使用for in循环进行遍历。for in循环遍历的是数组的索引,而不是数组的值。例如: for (var index in arr) { console.log(arr[index]); } 这段代码会按顺序遍历数组arr的每个元素,并打印出来。 6. 使用filter方法进行遍历和筛选。filter方法也接受一个回调函数作为参数,该函数在遍历数组的每个元素时被调用,并返回一个满足某个条件的新数组。例如: let newArr = arr.filter(item => { return item < 3; }); 这段代码会返回一个新数组newArr,其包含数组arr小于3的元素。 7. 使用find方法进行遍历。find方法也接受一个回调函数作为参数,该函数在遍历数组的每个元素时被调用,直到找到满足某个条件的元素为止。例如: let result = arr.find(item => { return item === 3; }); 这段代码会返回数组arr第一个等于3的元素。 以上是JavaScript常用几种遍历数组的方法。根据实际需求选择合适的方法来进行遍历。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [JS遍历数组的十五种方法](https://blog.csdn.net/weixin_39987434/article/details/130869691)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁锤妹妹@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值