能,for...of可直接遍历普通数组,因其原生实现[Symbol.iterator];需用arr.entries()解构获取索引和值;稀疏数组中空位视为undefined;Map/Set等可迭代,Object则需转为keys/values/entries。

for...of 能直接遍历普通数组吗
能,而且是最自然的用法。for...of 专为可迭代对象设计,而 Array 原生实现了 [Symbol.iterator] 方法,所以普通数组开箱即用,不需要额外处理。
常见错误是误写成 for...in——它遍历的是索引(字符串),且会枚举原型链上的可枚举属性,对数组完全不适用。
- 正确写法:
for (const item of arr) { ... } - 错误写法:
for (const i in arr) { ... }(得到的是"0","1"等字符串,不是值) - 注意:
for...of无法直接获取索引,如需索引,改用entries()或配合Array.prototype.keys()
如何在 for...of 中同时拿到值和索引
数组的 entries() 方法返回一个可迭代的键值对([index, value]),正好匹配 for...of 的解构能力。
性能上几乎没有损耗,因为 entries() 是惰性求值,不会提前生成完整新数组。
- 写法:
for (const [i, item] of arr.entries()) { ... } - 等价但啰嗦:
for (const pair of arr.entries()) { const i = pair[0]; const item = pair[1]; ... } - 别用
arr.keys()或arr.values()单独遍历——前者只给索引,后者只给值,无法兼顾
for...of 遍历稀疏数组时的行为
稀疏数组(比如 const arr = [1, , 3],中间有空位)在 for...of 中会把空位当作 undefined 处理,但不会跳过——它按实际长度迭代,每个位置都产出一个值(即使是 undefined)。
这和 forEach() 不同:forEach() 会跳过空位,而 for...of 不会。
- 示例:
for (const x of [1, , 3]) console.log(x)输出1、undefined、3 - 如果业务逻辑依赖“是否为空位”,不能只靠
=== undefined判断,得结合arr.hasOwnProperty(i)或Object.hasOwn(arr, i) - 转换为稠密数组再遍历?不推荐——
arr.filter(() => true)会丢掉undefined和null,行为不可控
为什么 map/set/arguments 也能用 for...of,但 Object 不行
for...of 只认 [Symbol.iterator] 接口。原生 Map、Set、类数组(如 arguments、NodeList)都实现了该接口;而普通对象 {} 没有,所以直接 for...of {} 会报 TypeError: {} is not iterable。
想遍历对象属性?必须显式转成可迭代形式:
- 键:
for (const key of Object.keys(obj)) { ... } - 值:
for (const val of Object.values(obj)) { ... } - 键值对:
for (const [k, v] of Object.entries(obj)) { ... } - 注意:
Object.keys()返回数组,所以本质还是在遍历数组,不是对象本身
真正容易被忽略的是:自定义类如果想支持 for...of,必须手动部署 [Symbol.iterator] 方法,否则哪怕有 length 和数字键,也不会被识别。

















