【Javascript】关于如何使用循环,看这篇就够了

2024-08-21 10:20
文章标签 java 使用 script 循环 这篇

本文主要是介绍【Javascript】关于如何使用循环,看这篇就够了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

每种编程语言都有循环。循环执行某个操作(也就是一段工作)多次,通常是对数组或列表中的每一项进行操作,或者重复执行直到满足某个条件为止。

JavaScript 尤其提供了多种不同类型的循环。我自己甚至都没有用过所有这些类型,出于好奇心,我想做个高层次的概览。结果发现,至少有几种循环类型没被广泛采用是有充分理由的。

那么,咱们就先用 for 循环开始,花点 while 时间来探索各种不同的循环类型,看看我们能用 each 做些什么,以及为什么你可能会选择一种而非另一种。读到最后你会觉得我这里的小文字游戏绝对逗乐。

whiledo...while 循环

首先登场的是 while 循环。这是最基础的循环类型,在很多情况下也是最容易阅读和最快的。它通常用于做某件事直到满足某个条件。这也是最容易制造无限循环或永不停止的循环的方式。还有 do...while 语句。实际上,唯一的区别在于条件是在每次迭代的末尾而不是开头检查。

// 从数组中移除第一个元素并打印出来,直到数组为空
let queue1 = ["a", "b", "c"];while (queue1.length) {let item = queue1.shift();console.log(item);
}// 上面的相同逻辑,但也会打印数组为空时的信息
let queue2 = [];do {let item = queue2.shift() ?? "empty";console.log(item);
} while (queue2.length);

for 循环

接下来是 for 循环。如果你需要重复执行某个操作一定次数,比如十次,那这就是首选。这种循环对编程新手来说可能有点吓人,但是把相同的循环用 while 风格重写一下,可以帮助理解语法,也更容易记住。

// 打印数字 1 到 5
for (let i = 1; i <= 5; i++) {console.log(i);
}// 同样的事情,但是用 `while` 循环实现
let i = 1; // `for` 循环的第一部分// 第二部分
while (i <= 5) {console.log(i);i++; // 第三部分
}("end");

for...offor await...of 循环

for...of 循环是最简单的方式来遍历数组。

let myList = ["a", "b", "c"];for (let item of myList) {console.log(item);
}

不过它们不仅仅限于数组。技术上讲,它们可以遍历实现了所谓的 可迭代协议 的任何东西。有一些内置类型实现了该协议:数组、映射、集合和字符串,这些是最常见的,但你也可以在自己的代码中实现该协议。做法是在任意对象中添加一个 [Symbol.iterator] 方法,而这个方法应该返回一个迭代器。这有点让人困惑,但大概意思是可迭代的对象是一种特殊的方法,返回迭代器;可以说是迭代器的工厂方法。一种特殊的函数叫做 生成器,它既能返回可迭代对象也能返回迭代器。

let myList = {*[Symbol.iterator]() {yield "a";yield "b";yield "c";},
};for (let item of myList) {console.log(item);
}

上面提到的所有东西都有异步版本:异步可迭代对象、异步迭代器和异步生成器。你可以用 for await...of 来使用异步可迭代对象。

async function delay(ms) {return new Promise((resolve) => {setTimeout(resolve, ms);});
}// 这次我们不是创建一个可迭代对象,而是生成器
async function* aNumberAMinute() {let i = 0;while (true) {// an infinite loopyield i++;// pause a minuteawait delay(60_000);}
}// 它是一个生成器,所以我们需要自己调用它
for await (let i of aNumberAMinute()) {console.log(i);// stop after one hourif (i >= 59) {break;}
}

有一点不太明显的是,你可以用非异步可迭代对象与 for await...of 一起使用,而且完全没问题。然而反过来就不行;你不能用异步可迭代对象与 for...of 一起使用。

forEachmap “循环”

虽然这些严格意义上不算循环,但你可以用它们来遍历列表。

说说 forEach 方法吧。历史上它的速度远不如 for 循环。我认为现在有些情况下这种情况可能已经改变,但如果性能是个问题,我还是会避免使用它。有了 for...of 之后,我不确定还有什么理由要用它。也许唯一的原因是你已经有了一个可以直接作为回调使用的函数,但你也可以很容易地在 for...of 的主体里调用同一个函数。

forEach 还接收每个元素的索引,所以这可能是你需要的功能。最终是否使用它,可能会取决于你正在处理的其他代码是否也在使用它,但如果是新写的代码我个人会尽量避免使用它。

let myList = ["a", "b", "c"];for (let item of myList) {console.log(item);
}// 如果我需要索引,或许可以用 `forEach`
["a", "b", "c"].forEach((item, index) => {console.log(`${index}: ${item}`);
});

同时,map 实质上是将一个数组转换为另一个数组。它与 forEach 一样有性能影响,但它比替代方案更好读一点。当然这是主观判断,就像 forEach 一样,你会希望遵循你的其他代码的做法。在 React 和受 React 启发的库中,你会经常看到它作为遍历数组并在 JSX 中输出项目列表的主要方式。

function MyList({items}) {return (<ul>{items.map((item) => {return <li>{item}</li>;})}</ul>);
}

for...in 循环

说到 JavaScript 中的循环,如果不提 for...in 语句,这个列表就不完整了,因为它可以遍历对象的字段。它还会遍历通过对象原型链继承的字段,这正是我一直避免使用它的原因。

话虽如此,如果你有一个对象字面量,那么 for...in 可能是遍历该对象键的有效方式。值得一提的是,如果你编写 JavaScript 已经有一段时间了,你可能还记得键的顺序曾经在不同浏览器之间不一致,但现在顺序是一致的。任何可能作为数组索引的键(即正整数)都会按升序排列在前面,然后是按声明顺序排列的其他键。

let myObject = {a: 1,b: 2,c: 3,
};for (let k in myObject) {console.log(myObject[k]);
}

结语

循环是许多程序员每天都在使用的东西,尽管我们可能会习以为常,不太去思考它们。

但当你退一步来看我们在 JavaScript 中遍历事物的各种方式时,你会发现其实有很多种方法可以做到这一点。不仅如此,它们之间存在显著——即使细微——的区别,这些差异确实会影响你的编写方式。

这篇关于【Javascript】关于如何使用循环,看这篇就够了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1092886

相关文章

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依

SpringBoot整合OpenFeign的完整指南

《SpringBoot整合OpenFeign的完整指南》OpenFeign是由Netflix开发的一个声明式Web服务客户端,它使得编写HTTP客户端变得更加简单,本文为大家介绍了SpringBoot... 目录什么是OpenFeign环境准备创建 Spring Boot 项目添加依赖启用 OpenFeig

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

SpringBoot整合mybatisPlus实现批量插入并获取ID详解

《SpringBoot整合mybatisPlus实现批量插入并获取ID详解》这篇文章主要为大家详细介绍了SpringBoot如何整合mybatisPlus实现批量插入并获取ID,文中的示例代码讲解详细... 目录【1】saveBATch(一万条数据总耗时:2478ms)【2】集合方式foreach(一万条数

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

SpringBoot中配置文件的加载顺序解读

《SpringBoot中配置文件的加载顺序解读》:本文主要介绍SpringBoot中配置文件的加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot配置文件的加载顺序1、命令⾏参数2、Java系统属性3、操作系统环境变量5、项目【外部】的ap

使用Python实现矢量路径的压缩、解压与可视化

《使用Python实现矢量路径的压缩、解压与可视化》在图形设计和Web开发中,矢量路径数据的高效存储与传输至关重要,本文将通过一个Python示例,展示如何将复杂的矢量路径命令序列压缩为JSON格式,... 目录引言核心功能概述1. 路径命令解析2. 路径数据压缩3. 路径数据解压4. 可视化代码实现详解1

Pandas透视表(Pivot Table)的具体使用

《Pandas透视表(PivotTable)的具体使用》透视表用于在数据分析和处理过程中进行数据重塑和汇总,本文就来介绍一下Pandas透视表(PivotTable)的具体使用,感兴趣的可以了解一下... 目录前言什么是透视表?使用步骤1. 引入必要的库2. 读取数据3. 创建透视表4. 查看透视表总结前言