如何在JavaScript中使用for循环
前言
循环允许我们通过循环数组或对象中的项并做一些事情,比如说打印它们,修改它们,或执行其他类型的任务或动作。JavaScript有各种各样的循环,for循环允许我们对一个集合(如数组)进行迭代。
在这篇文章中,我们将了解JavaScript提供的for循环。我们将看看for...in循环语句是如何在JavaScript中使用的,它的语法,它如何工作的例子,何时使用它或避免它,以及我们可以使用哪些其他类型的循环来代替。
为什么使用for循环
在JavaScript中,就像在其他编程语言中一样,我们使用循环来读取或访问集合中的项。这个集合可以是一个数组或一个对象。每当循环语句在一个集合中的项中循环时,我们称之为一个迭代。
有两种方式可以访问集合中的项。第一种方式是通过它在集合中的键,也就是数组中的索引或对象中的属性。第二种方式是通过集合项本身,而不需要键。
for…in循环的定义
JavaScript的for循环会或迭代集合中的键。使用这些键,你就可以访问它在集合中代表的项。
集合的项可以是数组,也可以是对象,甚至可以是字符串。
for…in循环的语法
for循环具有以下语法或结构:
for (let key in value) {
//do something here
}
在上述代码块中,value是我们迭代的项的集合。它可以是对象、数组、字符串等等。key会是value每一项的键,在每次迭代中都会改变到列表中的下一个键。
注意,这里我们使用let或const来声明key。
在对象中使用for…in循环
在JavaScript中使用for...in循环迭代对象时,其迭代的键或者属性是对象自己的属性(在上面的示例中,由key变量表示)。
由于对象可能通过原型链继承数据项,其中包括对象的默认方法和属性,以及我们可能定义的对象原型,因此我们应该使用hasOwnProperty。
在下面的例子中,我们通过变量obj进行循环,并打印每一个属性和值:
const obj = {
"a": "JavaScript",
1: "PHP",
"b": "Python",
2: "Java"
};
for (let key in obj) {
console.log(key + ": " + obj[key] )
}
// Output:
// "1: PHP"
// "2: Java"
// "a: JavaScript"
// "b: Python"
请注意,键的迭代顺序是升序的(也就是说,从数字开始,按数字的顺序,然后是字母,按字母的顺序)。然而,这个输出的顺序与初始化对象时创建的项的索引顺序不同。
在数组中使用for…in循环
在JavaScript中使用for...in循环来迭代数组时,在这种情况下,key将是元素的索引。然而,索引可以按随机顺序迭代。
因此,如果我们上面展示的for...in循环语法结构中的value变量是一个包含五项的数组,那么key就不能保证是0到4。一些索引可能会在其他索引之前。关于何时可能发生这种情况的细节将在本文后面解释。
在下面的例子中,我们对arr变量进行循环:
const arr = ["JavaScript", "PHP", "Python", "Java"];
for (let key in arr) {
console.log(key + ": " + arr[key])
}
// Output:
// "0: JavaScript"
// "1: PHP"
// "2: Python"
// "3: Java"
在循环中,我们呈现每个数组元素的索引和值。
在字符串中使用for…in循环
你可以在JavaScript中使用for…in循环来循环字符串。然而,不推荐这么做,因为你将在字符串的索引上循环,而不是字符串本身。
在下面的例子中,我们对str变量进行循环:
const str = "Hello!";
for (let key in str) {
console.log(key + ": " + str.charAt(key));
}
//Output
// "0: H"
// "1: e"
// "2: l"
// "3: l"
// "4: o"
// "5: !"
在这个循环中,我们要呈现每个字符的键或索引,以及该索引的字符。
让我们看看JavaScript for…in循环最适合的情况。
使用for…in循环迭代对象
因为for...in循环只迭代对象的可枚举属性,也就是对象自有属性,而不是像toString这样属于对象原型的属性。所以使用for...in循环来迭代对象是很好的。for...in循环提供了一个简单的方法来迭代一个对象的属性并最终得到它的值。
使用for…in循环调试
JavaScript for...in循环的另一个很好的用例是调试。比如,你可能想向控制台或HTML元素打印一个对象的属性和它的值。在这种情况下,for...in循环是一个不错的选择。
当使用for…in循环调试对象以及对象的值时,你应该始终记住,迭代是没有顺序的。也就是说,迭代的顺序是随机的。所以,访问属性的顺序可能与预期不同。
不使用for…in循环的情形
现在让我们来看看for...in循环不是最佳选择的情况。
数组的有序迭代
由于使用for...in循环时不能保证迭代中的索引顺序,如果有必要保持顺序,建议不要迭代数组。
如果你想支持像IE这样的浏览器,这一点尤其重要,因为IE是按照数组项创建的顺序而不是按照索引的顺序进行迭代的。这与当前现代浏览器的工作方式不同,后者是根据索引的升序来迭代数组的。
举例来说,如果你有一个包含四项的数组,你在索引3的位置插入了一项,在现代浏览器中,for...in循环仍然会按照从0到4的顺序遍历数组。 在IE中,当使用for...in循环时,它将遍历一开始就在数组中的四个项目,然后再遍历在索引3的位置添加的那一项。
迭代时进行更改
对属性的任何添加、删除或修改都不能保证有序的迭代。应该避免在for...in循环中对属性进行更改。这主要是由于它的无序性。
因此,如果你在迭代到达某一项之前删除它,那么这项在整个循环中根本就不会被访问。
同样地,如果你对一个属性进行修改,并不能保证这项不会被再次访问。因此,如果一个属性被改变,它可能会在循环中被访问两次而不是一次。
除此之外,如果一个属性在迭代过程中被添加,那么它在迭代过程中可能会被访问,也可能根本不会被访问。
由于这些情况,最好避免在for...in循环中对一个对象进行任何修改、删除或添加。
下面是一个在for...in循环中添加元素的例子。我们可以看到第一个循环的结果,然后是在第一个循环中进行添加后的第二个循环的结果。
<h2>Before</h2>
<div id="loopResultsBefore"></div>
<h2>After</h2>
<div id="loopResultsAfter"></div>
const beforeDiv = document.getElementById('loopResultsBefore');
const afterDiv = document.getElementById('loopResultsAfter');
const obj = {
"a": "JavaScript",
1: "PHP",
"b": "Python",
2: "Java"
};
for (let key in obj) {
beforeDiv.innerHTML += key + ": " + obj[key] + "<br />";
if (!isNaN(key)) {
obj[key - 1] = obj[key];
}
}
for (let key in obj) {
afterDiv.innerHTML += key + ": " + obj[key] + "<br />";
}
// Before
// 1: PHP
// 2: Java
// a: JavaScript
// b: Python
// After
// 0: PHP
// 1: Java
// 2: Java
// a: JavaScript
// b: Python
正如你在上面的例子中看到的,被添加的元素并没有被迭代。
for循环的替代方案
forEach在JavaScript中是数组原型的一个方法,它允许我们在回调函数中遍历数组的元素和它们的索引。
回调函数是你传递给另一个方法或函数的函数,作为该方法或函数执行的一部分而被执行。当涉及到JavaScript中的forEach时,它意味着回调函数将在每个迭代中执行,接收迭代中的当前项作为参数。
举例来说,下面的语句使用forEach迭代arr变量,并在console中打印value:
arr.forEach((value) => console.log(value));
你也可以访问数组的索引:
arr.forEach((value, index) => console.log(value, index));
JavaScript forEach循环也可以使用Object.keys()来迭代对象,把你想迭代的对象传给它,它返回对象的自有属性数组:
Object.keys(obj).forEach((key) => console.log(obj[key]));
另外,如果你不需要使用Object.values()来访问属性,你可以用forEach来直接循环属性的值:
Object.values(obj).forEach((value) => console.log(value));
注意,Object.values()返回项的顺序与for...in相同。
总结
通过使用JavaScript for...in循环,我们可以循环对象的键或属性。在迭代对象属性或进行调试时,它可能很有用,但在迭代数组或对对象进行修改时,应该避免使用for...in循环。
以上就是文章的所有内容,如果对你有所帮助,欢迎收藏点赞转发~
如何在JavaScript中使用for循环的更多相关文章
- 深入理解javascript中的事件循环event-loop
前面的话 本文将详细介绍javascript中的事件循环event-loop 线程 javascript是单线程的语言,也就是说,同一个时间只能做一件事.而这个单线程的特性,与它的用途有关,作为浏览器 ...
- 如何在 JavaScript 中检查字符串是否包含子字符串?
如何在 JavaScript 中检查字符串是否包含子字符串? // var test4 = _.includes(string, substring); 该方法需要此文件 <script src ...
- 如何在Javascript中利用封装这个特性
对于熟悉C#和Java的兄弟们,面向对象的三大思想(封装,继承,多态)肯定是了解的,那么如何在Javascript中利用封装这个特性呢? 我们会把现实中的一些事物抽象成一个Class并且把事物的属性( ...
- [译]Javascript中的for循环
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- [译]Javascript中的do-while循环
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- JavaScript中的事件循环机制跟函数柯里化
一.事件循环机制的理解 test();//按秒输出5个5 function test() { for (var i = 0; i < 5; i++) { setTimeout(() => ...
- 深入了解 JavaScript 中的 for 循环
在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是: 简单for循环 for-in forEach 在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循 ...
- JavaScript中for..in循环陷阱介绍
for...in循环中的循环计数器是字符串,而不是数字它包含当前属性的名称或当前数组元素的索引,下面有个不错的示例大家可以参考下 大家都知道在JavaScript中提供了两种方式迭代对象: (1) ...
- JavaScript 中 for in 循环和数组的问题
本文由 伯乐在线 - ElvisKang 翻译,进林 校稿.未经许可,禁止转载!英文出处:adripofjavascript.com.欢迎加入翻译小组. JavaScript的for…in循环用于迭代 ...
- javascript中for/in循环及使用技巧
JavaScript 支持不同类型的循环: for - 循环代码块一定的次数 for/in - 循环遍历对象的属性 while - 当指定的条件为 true 时循环指定的代码块 do/while - ...
随机推荐
- git revert总结
git revert git revert 是一种创建一次新的commit 来回退某次或某几次commit的一种方式 命令 // 创建一个新的commit,这个commit会删除(下面)commit- ...
- [CG] 顶点动画贴图 (Vertex Animation Texture, VAT)
什么是顶点动画? 简单来说,通过改变网格顶点的位置,使网格变形从而做成的动画.顶点动画的灵活度要远远高于骨骼动画.骨骼动画是靠骨骼(一堆有层级结构的节点,数量应该是远远小于网格顶点的数量的)的变化来驱 ...
- torch.max与torch.argmax
形式: torch.max(input) → Tensor 返回输入tensor中所有元素的最大值: a = torch.randn(1, 3) >>0.4729 -0.2266 -0.2 ...
- C语言输入输出格式符
C语言输入输出格式符 printf函数(格式输出函数) 1.一般格式 printf(格式控制,输出表列) 例如:printf("i=%d,ch=%c\n",i,ch); 说明: ( ...
- .NET 7 RC1 正式发布
从年初2 月份发布第一个预览版,经历7个预览版后,Microsoft 西雅图时间9月14日发布了 .NET 7 RC 1:https://devblogs.microsoft.com/dotnet/a ...
- 命令行配置Windows高级防火墙
今天正好看到个帖子,询问如何通过命令行配置防火墙策略中远程IP的地址,特别是添加新的地址. 就是图中Scope里Remote IP address的地址. 第一反应就是用netsh firewall来 ...
- DFS文件夹无法访问
最近DFS的文件服务器出现了部分文件和文件夹无法访问的情况.客户端直接访问DFS成员的共享文件夹时有是会出现Element not found的错误.有时打开文件的时候会出现文件不存在,或者你没有权限 ...
- MySQL集群搭建(2)-主主从模式
1 环境准备 上次我们搭建了主备架构,如下所示 这次我们的搭建目标是 具体配置信息 IP 系统 端口 MySQL版本 节点 读写 说明 192.168.41.83 Centos6.8 3306 5.7 ...
- 复现禅道V16.5的SQL注入(CNVD-2022-42853)
漏洞详情 禅道V16.5未对输入的account参数内容作过滤校验,导致攻击者拼接恶意SQL语句执行. 环境搭建 环境下载:禅道V16.5 下载后双击运行,进入目录运行start.exe 直接访问即可 ...
- Elasticsearch from/size-浅分页查询-深分页 scroll-深分页search_after深度查询区别使用及应用场景
Elasticsearch调研深度查询 1.from/size 浅分页查询 一般的分页需求我们可以使用from和size的方式实现,但是这种的分页方式在深分页的场景下应该是避免使用的.深分页的页次增加 ...