for循环最稳妥但需防length被改;for...of简洁适合纯读取,跳过稀疏数组空位;for...in慎用于数组,遍历对象属性名且顺序不定;Object.entries()兼顾键值、可读性与安全性。
length 被修改的风险直接用 for (let i = 0; i 是最兼容、最可控的方式,尤其适合需要索引、中途 break 或修改原数组的场景。
arr.length 每次都重新读取,如果循环中意外 push 或 splice 数组,可能造成死循环或跳项const len = arr.length; for (let i = 0; i
for (let i = arr.length - 1; i >= 0; i--),避免索引错位for...of 遍历数组更简洁,但拿不到索引它按顺序消费数组的 Symbol.iterator,语义清晰,适合纯读取场景。
let i = 0; for (const item of arr) { console.log(i++, item); }
arguments、NodeList)——除非它们有原生迭代器或已转成数组undefined 或稀疏数组(如 [1, , 3])时,for...of 会跳过空位,而传统 for 会访问到 undefined
const arr = [1, , 3];
for (const item of arr) {
console.log(item); // 输出:1,然后是 3(跳过了空位)
}for...in 不该用来遍历数组,但能遍历对象自有属性for...in 枚举的是对象的**可枚举属性名**(字符串),不是值,也不保证顺序。对数组来说,它遍历的是索引字符串("0"、"1"),还可能包含原型链上的属性。
for...in 可能遍历到意外添加的方法(如 arr.customMethod = () => {})obj[key] 取值;若对象有继承属性且未设 enumerable: false,也会被枚举出来Object.keys(obj).forEach(key => {...}) 或 Object.entries(obj)
const obj = { a: 1, b: 2 };
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
console.log(key, obj[key]); // 加这层判断才相对可靠
}
}Object.entries(),兼顾键、值和可读性它返回一个二维数组([["key1", val1], ["key2", val2]]),天然适配 for...of 和数组方法。
for...in + hasOwnProperty 更简洁,也避免了属性枚举顺序不可靠的问题for (const [key, value] of Object.entries(obj))
Symbol 键;要包含 Sy
Object.getOwnPropertySymbols() 单独处理for...in,但绝大多数业务场景无感知有些开发者以为 for...of 能直接遍历普通对象,结果报 TypeError: obj is not iterable —— 这个错误提示其实很准确:对象默认没有 [Symbol.iterator],得靠 Object.entries() 这类显式转换来“赋予”遍历能力。