JavaScript数组遍历的各种方式

news/2024/11/30 18:40:25/

 

目录

第一种方式(for循环)

第二种方式(forEach 遍历)

第三种方式(for...in)

第四种方式(for...of)

第五种方式(map方法遍历)

六、性能对比


第一种方式(for循环)

原始的for循环,也是最常见的一种遍历方式,示例如下所示:

let my_array = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
for (let i = 0; i < my_array.length; i++) {console.log(my_array[i]);// 打印// 10// 20// 30// 40// 50// 60// 70// 80// 90// 100
}

第二种方式(forEach 遍历)

可以通过数组原型上的方法(forEach)进行遍历,示例如下:

let my_array = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
my_array.forEach((res, index, e)=>console.log(res, index, e))
// 打印
// 10 0 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 20 1 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 30 2 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 40 3 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 50 4 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 60 5 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 70 6 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 80 7 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 90 8 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 100 9 [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

语法:

forEach(callbackFn)

forEach(callbackFn, thisArg)

callbackFn

回调函数为数组中每个元素执行的函数。并会丢弃它的返回值。该函数被调用时将传入以下参数:

element

数组中正在处理的当前元素。

index

数组中正在处理的当前元素的索引。

array

调用了 forEach() 的数组本身。

thisArg 可选

执行 callbackFn 时用作 this 的值。如果是采用箭头函数的形式,此参数就显得无关紧要了。

返回值

undefined

描述:

forEach() 方法是一个迭代方法
。它按索引升序地为数组中的每个元素调用一次提供的 callbackFn 函数。与 map()
 不同,forEach() 总是返回 undefined
,而且不能继续链式调用。其典型的用法是在链式调用的末尾执行某些操作。

callbackFn 仅对已赋值的数组索引调用。对于稀疏数组
中的空槽,它不会被调用。

实例如下:

let my_array = new Array(10);
my_array.forEach(res=>console.log(res + '这是测试稀疏数组'));

运行代码,发现没有也没打印。

forEach() 不会改变其调用的数组,但是,作为 callbackFn 的函数可以更改数组。请注意,在第一次调用 callbackFn 之前,数组的长度已经被保存。因此:

  • 当调用 forEach() 时,callbackFn 不会访问超出数组初始长度的任何元素。
  • 已经访问过的索引的更改不会导致 callbackFn 再次调用它们。
  • 如果 callbackFn 更改了数组中已经存在但尚未访问的元素,则传递给 callbackFn 的值将是在访问该元素时的值。已经被删除的元素不会被访问。

示例如下所示:

let my_array = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
my_array.forEach((res, index, e)=>{if(!index){my_array.push(1000)}console.log(res)
})
// 打印
// 10
// 20
// 30
// 40
// 50
// 60
// 70
// 80
// 90
// 100

发现在遍历数组时,新增的数据并没有打印出来。

除非抛出异常,否则没有办法停止或中断 forEach() 循环。如果有这样的需求,则不应该使用 forEach() 方法。

可以通过像  for、for...of 和 for...in 这样的循环语句来实现提前终止。当不需要进一步迭代时,诸如 
some()、find() 和 findIndex() 等数组方法也会立即停止迭代。

forEach() 返回的是一个同步函数,它不会等待 Promise 的返回。

第三种方式(for...in)

for...in 语句以任意顺序迭代一个对象的除Symbol以外的可枚举属性,包括继承的可枚举属性。

语法

for (variable in object)

  statement

variable

在每次迭代时,variable 会被赋值为不同的属性名。

object

非 Symbol 类型的可枚举属性被迭代的对象。

注意:for ... in是为遍历对象属性而构建的,不建议与数组一起使用。

代码示例如下所示:

let my_array = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
for (let index in my_array) {console.log(index, my_array[index]);
}
// 打印
// 0 10
// 1 20
// 2 30
// 3 40
// 4 50
// 5 60
// 6 70
// 7 80
// 8 90
// 9 100

第四种方式(for...of)

for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。

语法:

for (variable of iterable) {

    //statements

}

variable

在每次迭代中,将不同属性的值分配给变量。

iterable

被迭代枚举其属性的对象。

示例如下所示:

let my_array = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
for (let v of my_array) {console.log(v);
}
// 打印
// 10
// 20
// 30
// 40
// 50
// 60
// 70
// 80
// 90
// 100

对于for...of的循环,可以由 break, throw 或 return 终止。在这些情况下,迭代器会进行关闭。

示例代码如下所示:

let my_array = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
for (let v of my_array) {if(v > 60) {break;}console.log(v);
}
// 打印
// 10
// 20
// 30
// 40
// 50
// 60

第五种方式(map方法遍历)

map() 方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。

语法

map(callbackFn)

map(callbackFn, thisArg)

参数

callbackFn

为数组中的每个元素执行的函数。它的返回值作为一个元素被添加为新数组中。该函数被调用时将传入以下参数:

element

数组中当前正在处理的元素。

index

正在处理的元素在数组中的索引。

array

调用了 map() 的数组本身。

thisArg (可选)

执行 callbackFn 时用作 this 的值。

map() 方法是一个迭代方法。它为数组中的每个元素调用一次提供的 callbackFn 函数,并用结果构建一个新数组。

map() 方法是一个复制方法。它不会改变 this。然而,作为 callbackFn 提供的函数可以更改数组。请注意,在第一次调用 callbackFn 之前,数组的长度已经被保存。因此:

  • 当开始调用 map() 时,callbackFn 将不会访问超出数组初始长度的任何元素。
  • 对已访问索引的更改不会导致再次在这些元素上调用 callbackFn
  • 如果数组中一个现有的、尚未访问的元素被 callbackFn 更改,则它传递给 callbackFn 的值将是该元素被修改后的值。被删除的元素则不会被访问。

一般数组常用的遍历方式大概就是这5种。

六、性能对比

Benchmark.js 是 loash的作者(John-David Dalton)创建的一个用于基准测试的类库。首先我们引入Benchmark.js 进行基准测试。

Benchmark.js 如何使用可参考github地址:GitHub - bestiejs/benchmark.js: A benchmarking library. As used on jsPerf.com.A benchmarking library. As used on jsPerf.com. Contribute to bestiejs/benchmark.js development by creating an account on GitHub.https://github.com/bestiejs/benchmark.js我们创建一个数组,包含10000个元素,然后通过上面5种方式遍历以下,对比以下性能,代码如下所示:

var Benchmark = require('benchmark');var suite = new Benchmark.Suite;
var array10000 = Array.from({ length: 10000 }, (o, i) => i + 1);
// 增加测试
suite.add('for#Array', function() {for(let i = 0; i < array10000.length; i++){}
})
.add('forEach#Array', function() {array10000.forEach(res=>{})})
.add('forIn#Array', function() {for (let i in array10000){}
})
.add('forOf#Array', function() {for (let i of array10000){}})
.add('map#Array', function() {array10000.map(res=>{})
})
// 增加监听
.on('cycle', function(event) {console.log(String(event.target));
})
// 最后一个测试的完成事件
.on('complete', function() {console.log('Fastest is ' + this.filter('fastest').map('name'));
})
// 是否异步运行
.run({ 'async': true });

执行结果如下所示:

for#Array x 398,690 ops/sec ±0.58% (92 runs sampled)
forEach#Array x 94,419 ops/sec ±40.29% (88 runs sampled)
forIn#Array x 6,170 ops/sec ±2.58% (90 runs sampled)
forOf#Array x 238,086 ops/sec ±1.47% (93 runs sampled)
map#Array x 26,244 ops/sec ±17.69% (86 runs sampled)
Fastest is for#Array

Ops/sec: 代表以每秒钟执行代码的次数

±17.69%:  方差,波动越小,数据越稳定。方差的稳定性也和抽样数也会有影响,一般来说,抽样样本越多,方差波动越小,数据越稳定。

88 runs sampled :运行88个抽样

从以上返回的结果来看,数组遍历的时候性能从高到低的依次是:

For > for of > forEach > map > for in

结论:

这只是一个大概的测试结果,影响测试的结果也包括运行数据的大小,运行抽样数据的大小等因素。但是这也可以基本反映出它们各自的一个性能。

 


http://www.ppmy.cn/news/579177.html

相关文章

手机wap端用户注册表单(html+css)

实现效果&#xff1a; html代码&#xff1a; <div class"login"><form action"*跳转接口*" method"post" onsubmit"return checkForm()"><div class"mt30"> <span>输入手机号码</span>&l…

手机wap浏览器下载选哪家

如果问你你知道的手机wap浏览器有哪些&#xff1f;相信大家都会说出那么一两个出来。在手机wap浏览器下载的时候相信大家也会有自己的想法&#xff0c;今天我们就是来介绍三款手机浏览器的&#xff0c;希望通过比较能帮助你更好的选择。 首先是UC&#xff0c;其实说到手机wap浏…

手机wap网站制作教程

随着智能手机的普遍使用&#xff0c;移动互联网用户的数量随之猛增。当我们关注PC电脑网站制作的时候&#xff0c;一定不要忘了制作一个手机网站。这样我们的网站用户就可以轻松使用手机浏览我们自己做的网站了。 如何建手机网站详细步骤 制作手机网站之前&#xff0c;需制作一…

【带移动搜索功能】织梦dedecms手机WAP插件专业版 织梦自动建手机WAP站 PC+WAP数据同步更新 访问自动跳转

安装步数&#xff1a; &#xff08; 插件及高清视频教程&#xff1a;QQ 86862635 或www.wlyx158.com 搜索 织梦自动建手机WAP站 PCWAP数据同步更新&#xff09; 1. 检查数据表的前缀是不是dede_ &#xff08; 如果修改了前缀就不能用 &#xff09; 2. 启用支持多站点 系统…

wap手机 建站

做一个WAP网站&#xff0c;其实也没有那么神秘&#xff0c;甚至比PC版的网站还要容易些&#xff0c;因为很少图片和样式&#xff0c;返璞归真。 一、用什么来开发&#xff1f; 据说以前的手机版要用什么WML&#xff0c;我没学过&#xff0c;一听头都大了&#xff0c;时间花费不…

php最底部悬浮层,适用于手机Wap页面和所有网页页面

如上图所示&#xff0c;样式可根据自己的需要进行修改&#xff0c;源码下载地址&#xff1a;http://download.csdn.net/detail/ougexingfuba/9923775

Wap模拟器,用电脑浏览器浏览手机wap网站

s 先介绍一下什么是WAP浏览器。WAP浏览器&#xff0c;WAP Browser&#xff0c;又叫WAP微型浏览器&#xff0c;是用在手机或pda等设备上浏览WAP站点的工具。它与PC上的web浏览器比如ie、firefox相似。但由于手机wap站点用的是WML之类的语言&#xff0c;所以web浏览器并不能直接浏…

移动端mui框架写的手机wap模板

mui框架手机报考驾校预约&#xff1a; http://www.sucaihuo.com/templates/2139.html mui框架汽车美容维修4S店&#xff1a; http://www.sucaihuo.com/templates/2081.html 有赞微信端登录注册手机wap模板&#xff1a; http://www.sucaihuo.com/templates/1582.html 养老惠手…