JavaScript数组遍历的各种方式

news2024/11/23 0:44:23

 

目录

第一种方式(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.coloradmin.cn/o/685740.html

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

相关文章

【yolov5系列】将yolov5s模型部署到SigmaStar的9383芯片上

今年年初&#xff0c;接触了星宸科技&#xff08;sigmastar&#xff09;的芯片9383&#xff0c;将深度学习模型进行部署&#xff0c;使用sigmastar的深度学习加速硬件IPU进行模型推理。这里简单记录下sigmastar相关内容。 补充说明&#xff0c;之前使用的是瑞芯微的芯片&#x…

大数据从0到1的完美落地之Flume案例_3

案例演示 案例演示&#xff1a;SyslogtcpMemLogger Syslogtcp: syslog广泛应用于系统日志。syslog日志消息既可以记录在本地文件中&#xff0c;也可以通过网络发送到接收syslog的服务器。接收syslog的服务器可以对多个设备的syslog消息进行统一的存储&#xff0c;或者解析其中…

经济统计类的实证论文解剖

整理来源 UP主&#xff1a;Michaelscholar https://space.bilibili.com/550661456/video 截图 1.读什么文献 国内&#xff1a;中文CSSCI 期刊&#xff1a;中国社会科学&#xff0c;经济研究&#xff0c;经济学&#xff08;季刊&#xff09;&#xff0c;管理世界&#xff0…

MySQL数据库——主从复制

目录 前言一、读写分离概述1. 什么是读写分离&#xff1f;2. 为什么要读写分离呢&#xff1f;3. 什么时候要读写分离&#xff1f;4. 主从复制与读写分离5. mysq支持的复制类型6. 主从复制的工作过程7. MySQL主从复制延迟 二、主从复制配置方法 前言 在实际的生产环境中&#x…

c++ GoogleTest编译使用

编译 1.下载zip源码 2.解压&#xff0c;使用cmake生成工程 第一处填解压生成的文件夹 第二处的build路径可以不存在&#xff0c;点击configure会cmake提示创建 弹出界面中要选择自己的vs版本&#xff0c;选择finish。 然后点击generate&#xff0c;然后点击open Project。 生…

使用kubesphere搭建k8s集群

目录 1准备3台虚拟机 2 每台虚拟机更新yum的软件包&#xff0c;时间设置等 3 关闭防火墙 4 添加三台服务器的域名设置 5 设置三台服务器之间免密 6 安装kubesphere必要依赖&#xff0c;每个节点都要装&#xff0c;不然报错&#xff1a;socat not found in system path 7…

校园广播对讲音柱话筒

校园广播对讲话筒 校园广播对讲话筒&#xff1a;增强校园沟通的利器 提起校园广播对讲话筒&#xff0c;你或许会想到它在紧急情况下的应用。然而&#xff0c;这个功能强大的设备在校园内的广泛运用&#xff0c;不仅仅局限于危机解决。它成为了促进校园内部沟通、加强团队协作…

Tensorflow:from tensorflow.keras import layers 报错

执行代码&#xff1a; from tensorflow.keras import layers 报错&#xff1a; keras模块不存在 查&#xff0c;有其他博客表示keras包在tensorflow模块的pyhon包中&#xff1b; 于是&#xff1a; from tensorflow.python.keras import layers 在类似的如此调用keras的其…

chatgpt赋能python:Python能自动化办公吗?

Python能自动化办公吗&#xff1f; 在当今信息时代&#xff0c;办公工作中我们不可避免地要使用电脑&#xff0c;进行各种办公处理&#xff0c;比如文字处理、数据处理、图表制作等。这些操作看起来简单&#xff0c;但从事这些工作的人员都知道&#xff0c;日积月累之后&#…

【MySQL】不就是MySQL——多表查询综合练习

前言 嗨咯大家好&#xff01;我们学习完毕了多表查询&#xff0c;今天我们就要对我们所学的成果进行测验&#xff0c;本期主要是对多表查询相关内容的练习课程。可以先试着自己敲&#xff0c;遇到不会可以查看查考代码。 目录 前言 目录 练习题 1.查询员工的姓名、年龄、职位…

HDFS常见的Shell操作

HDFS常见的Shell操作 文章目录 HDFS常见的Shell操作写在前面基本语法HDFS命令大全常用命令实操准备工作上传文件下载文件HDFS直接操作 写在前面 Hadoop版本&#xff1a;Hadoop-3.xLinux版本&#xff1a;CentOS7.5 HDFS的Shell操作是入门Hadoop开发的学习重点 基本语法 Shell客…

分布式批处理:MapReduce初探

大家好&#xff0c;我是方圆。《数据密集型应用系统设计》第十章中有介绍到 MapReduce 相关的内容&#xff0c;当时觉得看得意犹未尽&#xff0c;所以便找了一些资料又看了一下。随着深入发现能扩展的东西实在太多&#xff0c;考虑时间有限&#xff0c;准备先把 MapReduce 基础…

基于smardaten无代码快速开发智慧城管系统

0️⃣需求背景 现代城市管理的面临着一系列问题&#xff1a;如执法人员不足、信息化手段应用少和时间处理不及时等&#xff0c;开发一个智慧城管回访系统的需求与日俱增… 通过引入智慧城管回访系统&#xff0c;可以提高城市管理的科学性、智能化和透明度&#xff0c;为城市发…

【软考网络管理员】2023年软考网管初级常见知识考点(14)- linux命令及目录相关详解

涉及知识点 Linux 目录结构&#xff0c; Linux 常用命令&#xff0c; Linux 下的文件基本属性&#xff0c; Linux 的启动与关闭 软考网络管理员常考知识点&#xff0c;软考网络管理员网络安全&#xff0c;网络管理员考点汇总。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》…

HTML5 游戏开发实战 | 推箱子

经典的推箱子是一个来自日本的古老游戏&#xff0c;目的是在训练玩家的逻辑思考能力。在一个狭小的仓库中&#xff0c;要求把木箱放到指定的位置&#xff0c;稍不小心就会出现箱子无法移动或者通道被堵住的情况&#xff0c;所以需要巧妙地利用有限的空间和通道&#xff0c;合理…

java9新特性之-String存储结构变更--集合工厂方法-- InputStream 加强--增强的 Stream API讲解

String存储结构变更 Motivation The current implementation of the String class stores characters in a char array, using two bytes (sixteen bits) for each character. Data gathered from many different applications indicates that strings are a major component o…

Ubuntu22.04编译安装FFmpeg

FFmpeg介绍 概述 FFmpeg是一款用C语言编写的跨平台免费开源多媒体处理工具&#xff0c;该软件可实现音视频的采集、编解码、转码、过滤以及流媒体相关操作等功能。 同时&#xff0c;FFmpeg也为其他多种语言和操作系统提供了开发组件&#xff0c;包括Java、Python、C等和Wind…

【吴恩达deeplearning.ai】基于LangChain开发大语言应用模型(下)

以下内容均整理来自deeplearning.ai的同名课程 Location 课程访问地址 DLAI - Learning Platform Beta (deeplearning.ai) LangChain for LLM Application Development 基于LangChain开发大语言应用模型&#xff08;上&#xff09; 一、LangChain: Q&A over Documents基于文…

SpringMVC原理分析 | Controller配置、RestFul风格

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Controller配置 控制器Controller 控制器复杂提供访问应用程序的行为&#xff0c;通常通过接口定义或注释定义的两种方法实现控制器负责解析用户的请求并将其转换为一…

ModaHub AI模型开源社区——Milvus向量数据库存储相关概念

目录 存储相关概念 分区和数据段 数据段&#xff08;segment&#xff09; 分区&#xff08;partition&#xff09; 集合、分区和数据段的关系 元数据 常见问题 存储相关概念 分区和数据段 建立集合时&#xff0c;Milvus 根据参数 index_file_size 控制数据段的大小。另…