for 、for-in、for-of、forEach 的区别,主要在于能否中断循环和遍历性能
语法
- for 循环
语法:
for (初始化; 条件; 迭代) { ... }
特点:
- 最基础的循环,通过索引遍历数组或类数组对象。
- 完全控制循环过程(步长、条件、中断)。
- 性能最优,无额外函数调用开销。
- 适用场景:需要精确控制循环逻辑(如倒序、步长调整)或高性能场景。 示例:
const arr = [1, 2, 3]
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
- for-in 循环
语法:
for (const key in object) { ... }
特点:
- 遍历对象的可枚举属性(包括原型链上的属性)。
- 不保证顺序,通常用于遍历对象键值对。
- 不适用于数组(可能遍历到非自有属性或方法)。
- 需配合 hasOwnProperty 过滤自有属性。
示例:
const obj = { a: 1, b: 2 }
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key])
}
}
- for-of 循环(ES6+)
语法:
for (const value of iterable) { ... }
特点:
- 遍历可迭代对象(如数组、字符串、Map、Set)。
- 按插入顺序遍历,直接获取元素值(非索引)。
- 可中断(支持 break 和 continue)。
- 适用场景:遍历数组、字符串或可迭代对象,需保持顺序或值操作。
示例:
const arr = ['a', 'b', 'c']
for (const value of arr) {
console.log(value)
}
- forEach 方法
语法:
array.forEach((value, index, array) => { ... });
特点:
- 数组专属方法,遍历数组元素。
- 不可中断(无法用 break 或 return 终止)。
- 函数式风格,简洁但性能略低于 for 循环。
- 适用场景:简单遍历数组,无需复杂逻辑。
示例:
const arr = [1, 2, 3]
arr.forEach((value, index) => {
console.log(value)
})
优缺点
-
for
- 优点:程序简洁,结构清晰,循环初始化,循环变量化和循环条件位置突出
- 缺点:结构比 while 循环复杂,容易出编码错误
- 适用场景:遍历数组,对象,字符串
- break、continue:支持
-
for-in
- 优点:可以使用 break、continue,不仅支持数组的遍历,还可以遍历类似数组的对象,支持字符串的遍历最简洁
- 缺点:适用于处理原有的原生对象
- 适用场景:遍历对象,遍历字符串
- break、continue:支持
-
for-of
- 优点:避免了 for-in 的所有缺点,支持 break、continue、return。支持遍历 map,object,array,set string 等
- 缺点:不适用于处理原有的原生对象
- 适用场景:遍历数组,遍历 map,object,set
- break、continue:支持
-
forEach
- 优点:便利的时候更加简洁,不用关心集合下标的问题,减少了出错的效率
- 缺点:不能同时遍历多个集合,在遍历的时候无法修改和删除集合数据,方法不能使用 break,continue 语句跳出循环,或者使用 return 从函数体返回,对于空数组不会执行回调函数
- 适用场景:遍历数组,遍历 map,object,set
- break、continue:不支持
关键区别总结
| 特性 | for | for-in | for-of | forEach |
|---|---|---|---|---|
| 目标类型 | 数组/类数组 | 对象属性 | 可迭代对象 | 数组 |
| 顺序保证 | ✅ | ❌ | ✅ | ✅ |
| 中断支持 | ✅ (break) | ✅ (break) | ✅ (break) | ❌ |
| 性能 | 最高 | 中等 | 高 | 中等 |
| 代码简洁性 | 低 | 低 | 高 | 最高 |
| 适用场景 | 复杂逻辑控制 | 对象遍历 | 可迭代对象遍历 | 简单数组遍历 |
使用建议
- 优先 for-of:遍历数组、字符串或可迭代对象。
- 优先 forEach:简单遍历数组且无需中断。
- 避免 for-in 遍历数组:可能遍历到非自有属性。
- 需要性能时选 for 循环:如处理大规模数据。