JavaScript 常用循环语句对比:for、for...in、for...of 与 forEach
本文详细对比JavaScript中四种常用循环语句:普通for、for...in、for...of和forEach。分析它们在Array、Object、Set和Map四种数据结构中的支持情况,重点讲解原型属性过滤、迭代器行为以及break/continue/return语句的使用限制,帮助开发者根据场景选择最合适的循环方式。
JavaScript提供了多种循环语句,包括普通for、for...in、for...of以及forEach。本文旨在对比这四种循环方式在Array、Object、Set(ES6新增)和Map(ES6新增)这四种数据结构中的支持情况及具体区别。
首先,我们需要构建用于测试的四种数据类型的数据样本。
let arr = [1, 2, 3, 4, 5, 6];
let obj = { a: 1, b: 2, c: 3 };
let map = new Map([['a', 'a1'], ['b', 'b2'], ['c', 'c3']]);
let set = new Set(['a', 'b', 'c']);
1 普通 for 循环
普通 for 循环在 Array 类型数据中可以直接使用。在遍历数组时,该循环机制实际上是在遍历数组的下标(索引),开发者需要通过获取到的下标来访问并取值。
for (let i = 0; i < arr.length; i++) { // i是下标(索引)
console.log(i)
console.log(arr[i])
}
2 for...in 循环
for...in 语句既可用于 Array,也可用于 Object。需要特别注意的是,该循环会遍历对象原型链上的属性,这意味着原型上定义的属性也会被枚举出来。
Array 场景
let arr = [1, 2, 3, 4, 5, 6];
Array.prototype.a = "1"
for (let i in arr) { // i是下标(索引)
console.log(i)
console.log(arr[i])
}
从运行结果可以看出,原型上定义的属性也被循环出来了,这通常并非开发者所期望的结果。我们可以通过 hasOwnProperty 方法来过滤掉继承自原型的属性,从而只获取对象自身的属性。
let arr = [1, 2, 3, 4, 5, 6];
Array.prototype.a = "1"
for (let i in arr) { // i是下标(索引)
if (arr.hasOwnProperty(i)) {
console.log(i)
console.log(arr[i])
}
}
Object 场景
let obj = { a: 1, b: '2', c: 3 };
Object.prototype.d = 4
for (let key in obj) { // key是键
console.log(key)
console.log(obj[key])
}
对于 Object 类型,同样存在原型属性被循环出来的问题。解决方法与 Array 一致,利用 hasOwnProperty 进行过滤即可排除原型属性。
for (let key in obj) { // key是键
if (obj.hasOwnProperty(key)) {
console.log(key)
console.log(obj[key])
}
}
3 for...of 循环
for...of 循环的支持范围更广,在 Array、Object、Set 和 Map 中均可使用。
Array 场景
虽然 Array 本质上也是对象,我们可以在其隐式原型(__proto__)中找到定义好的方法,但 for...of 提供了更直接的迭代方式。
for (let key of arr.keys()) { // key是下标
console.log(key)
}
for (let value of arr) { // value是值
console.log(value)
}
for (let value of arr.values()) { // value是值
console.log(value)
}
for (let [key, value] of arr.entries()) { // key是下标 value是值
console.log(key,value)
}
Object 场景
for (let [key, value] of Object.entries(obj)) { // key是下标 value是值
console.log(key, value)
}
Set 场景
由于 Set 数据结构本身不包含重复值,其 keys() 和 values() 方法返回的结果是一致的。因此,下面列出的四种遍历方式输出的结果是相同的。
for (let key of set.keys()) {
console.log(key)
}
for (let value of set) {
console.log(value)
}
for (let value of set.values()) {
console.log(value)
}
for (let [key, value] of set.entries()) {
console.log(key, value)
}
Map 场景
for (let key of map.keys()) {
console.log(key)
}
for (let value of map) {
console.log(value)
}
for (let value of map.values()) {
console.log(value)
}
for (let [key, value] of map.entries()) {
console.log(key, value)
}
在 for...of 循环中,可以使用 break 和 continue 语句来跳出或跳过当前迭代,也可以使用 return 语句从包含该循环的函数体中直接返回。
for (let key of arr.keys()) { // key是下标
if (key == 3) {
return
}
console.log(key)
}
for (let key of arr.keys()) { // key是下标
if (key == 3) {
break
}
console.log(key)
}
for (let key of arr.keys()) { // key是下标
if (key == 3) {
continue
}
console.log(key)
}
4 forEach 方法
forEach 方法在 Array、Set 和 Map 中均可使用。但与 for...of 不同,forEach 的回调函数内部不能使用 break 或 continue 语句来跳出循环,也不能通过 return 语句从外层函数返回。
Array 场景
arr.forEach((value, index) => {
console.log(value, index)
})
Set 场景
set.forEach((value, key) => {
console.log(value, key)
})
Map 场景
map.forEach((value, key) => {
console.log(value, key)
})
break、continue 和 return 的行为差异
在 forEach 中使用 continue 会触发语法错误提示。
Illegal continue statement: no surrounding iteration statement
在 forEach 中使用 break 同样会触发语法错误提示。
Illegal break statement
在 forEach 中使用 return,并不会像普通函数那样返回,而是仅仅结束当前这一次回调的执行,循环会继续执行后续元素。
5 总结
普通 for 循环适用于 Array,通过下标索引取值;for...in 适用于 Array 和 Object,但需注意过滤原型属性;for...of 支持 Array、Object、Set 和 Map,且支持 break、continue 和 return;forEach 适用于 Array、Set 和 Map,但不支持 break、continue 或 return 跳出循环。
至此,关于 JavaScript 常用 for 循环的详细对比介绍完毕。如需了解更多 JS for 循环相关内容,建议搜索本站过往文章或继续阅读后续系列文章,感谢大家的支持。
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
