主题
循环
循环用于重复执行一段逻辑。JavaScript 中常见的循环方式包括:
whiledo...whileforfor...infor...of
什么时候需要循环
循环通常用于:
- 遍历数组、对象、集合
- 重复执行某个任务直到满足条件
- 批量处理一组数据
while
while 适合“只要条件成立就持续执行”的场景。
js
let count = 3
while (count > 0) {
console.log(count)
count--
}它的特点是先判断条件,再决定是否执行循环体。
do...while
do...while 会先执行一次,再判断条件。
js
let count = 0
do {
console.log(count)
count--
} while (count > 0)这种写法不算高频,但在“循环体至少要执行一次”的场景里很直接。
for
for 是最常见的循环形式,适合计数式循环。
js
for (let i = 0; i < 3; i++) {
console.log(i)
}这三个部分分别表示:
- 初始化
- 继续条件
- 每轮结束后的更新动作
变量作用域
js
for (let i = 0; i < 3; i++) {
console.log(i)
}
// console.log(i) // i is not defined如果使用 let 声明循环变量,它只在当前循环块内有效。
break 和 continue
break
break 用于提前结束整个循环:
js
for (let i = 0; i < 10; i++) {
if (i === 5) {
break
}
console.log(i)
}continue
continue 用于跳过当前这一轮,直接进入下一轮:
js
for (let i = 0; i < 6; i++) {
if (i % 2 === 0) {
continue
}
console.log(i)
}这类写法常用于过滤不需要处理的项。
for...in
for...in 用于遍历对象的可枚举属性名。
js
const user = {
name: 'Lee',
age: 18,
}
for (const key in user) {
console.log(key, user[key])
}它拿到的是“键”,不是值。
适合场景
- 遍历普通对象属性
- 需要按键名读取值
注意点
如果只是想处理对象自己的键,很多时候 Object.keys()、Object.entries() 会更直观。
for...of
for...of 用于遍历可迭代对象的值,例如:
- 数组
- 字符串
SetMap
js
const list = [10, 20, 30]
for (const item of list) {
console.log(item)
}它拿到的是“值”,不是键。
for...in 和 for...of 的区别
for...in 遍历键名
遍历键名:
js
const arr = ['a', 'b']
for (const key in arr) {
console.log(key) // 0 1
}for...of 遍历值
遍历值:
js
const arr = ['a', 'b']
for (const value of arr) {
console.log(value) // a b
}日常开发里:
- 遍历对象属性,优先考虑
for...in或Object.keys - 遍历数组内容,优先考虑
for...of
标签语句
在多层嵌套循环中,有时需要直接跳出外层循环,可以配合标签使用 break:
js
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i + j > 2) {
break outer
}
}
}这类写法存在,但不宜滥用。多数情况下,提取函数或重构条件会更清晰。
forEach 不是语法级循环
数组的 forEach() 很常见,但它和 for、for...of 不完全是一类东西,它更像一个高阶方法。
js
;[1, 2, 3].forEach((item) => {
console.log(item)
})它适合简单遍历,但有几个限制:
- 不能直接用
break - 不能直接用
continue - 处理异步串行流程时不如
for...of直观
为什么 await 不适合直接放进 forEach
js
async function run() {
const list = [1, 2, 3]
list.forEach(async (item) => {
await request(item)
console.log(item)
})
console.log('end')
}这里 forEach 不会等待每个异步回调完成,因此通常会先打印:
js
end如果目标是串行执行,更适合写成:
js
async function run() {
const list = [1, 2, 3]
for (const item of list) {
await request(item)
console.log(item)
}
console.log('end')
}串行与并发
串行
js
for (const item of list) {
await request(item)
}适合前后有依赖、需要按顺序处理的任务。
并发
js
await Promise.all(list.map((item) => request(item)))适合互不依赖、希望一起执行的任务。
如何选择
用 for
适合:
- 明确知道起点、终点和步进
- 需要索引
用 while
适合:
- 循环次数不固定
- 更关注条件是否继续成立
用 for...of
适合:
- 遍历数组、字符串、集合
- 需要配合
await做串行异步处理
用 for...in
适合:
- 遍历对象属性名
使用建议
- 遍历数组时,优先考虑
for...of或数组方法。 - 遍历对象属性时,优先考虑
for...in或Object.keys()。 - 需要
break、continue或串行await时,不要首选forEach()。 - 复杂嵌套循环如果开始依赖标签跳转,通常说明代码可以进一步拆分。
