验证for...of/for...in与iterator/iterable的适用关系
结论验证与详细解释
你的两个结论都是完全正确的,咱们结合代码和JS的底层机制来一步步确认:
一、for...of可同时用于iterable(可迭代对象)和iterator(迭代器)
首先得明确两个核心概念:
- Iterable(可迭代对象):实现了
Symbol.iterator方法的对象,调用这个方法会返回一个iterator。比如你代码里的array1就是标准的可迭代对象。 - Iterator(迭代器):拥有
next()方法的对象,同时迭代器本身也实现了Symbol.iterator方法——这个方法会返回迭代器自身。这就意味着,迭代器本质上也是一种可迭代对象。
for...of的工作逻辑是:
- 调用目标对象的
Symbol.iterator方法,获取一个迭代器 - 不断调用迭代器的
next()方法,直到返回的对象done属性为true - 每次
next()返回的value就是遍历的内容
所以不管你给for...of传的是原始的可迭代对象(比如array1),还是已经拿到的迭代器(比如iterator),它都能正常工作:
- 遍历
array1时,for...of自动调用array1[Symbol.iterator]()拿到迭代器,再逐个取元素 - 遍历
iterator时,for...of调用iterator[Symbol.iterator](),得到的还是这个迭代器本身,接着继续调用next()输出值
你的代码已经验证了这一点:两种遍历都能得到预期的输出。
二、for...in仅可用于遍历对象的可枚举属性,无法作用于迭代器
for...in和迭代协议完全无关,它的作用是遍历对象自身和原型链上的可枚举属性名,和迭代器的next()机制没有任何交集。
- 对于数组
array1来说,它的索引(0、1、2)是可枚举的自有属性,所以for...in能遍历到这些索引,你通过array1[index]就能拿到对应元素。 - 但对于迭代器对象(比如
array1.keys()返回的迭代器),它的自有属性极少,而且原型链上的属性(比如next方法)默认都是不可枚举的。咱们补全你未完成的代码测试一下:
var array1 = ['a', 'b', 'c']; var iterator = array1.keys(); for (var key in iterator) { console.log(key); // 控制台没有任何输出 }
这就证明了for...in无法遍历迭代器的内容——因为迭代器的数据不是以可枚举属性的形式存储的,只能通过next()方法获取,而for...in不会去调用这个方法。
额外补充
要注意的是,for...in虽然能遍历数组,但并不推荐用来遍历数组元素:它可能会遍历到数组原型链上的自定义可枚举属性,而且遍历顺序不一定是严格的索引顺序。遍历数组优先用for...of、普通for循环或者数组的迭代方法(比如forEach)。
内容的提问来源于stack exchange,提问作者Prem
相关产品推荐
相关产品推荐

