在MDN官网学习for...of的时候,会发现for...of是这么描述的:for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,这句话的意思告诉我们不能for...of遍历普通对象,因为普通对象不是一个可迭代对象(iterable)。
那么问题来了,什么是可迭代对象?
可迭代对象,就是说可以通过某种方式逐个访问其中的元素。在JavaScript中,如字符串、数组、Set 对象、Map 对象等都是可迭代对象。通俗点说,可迭代对象就像是一串有序的数据组成的序列,可以通过循环或其他方式按序访问其中的每个数据。
怎样成为可迭代对象?
一个对象要成为可迭代对象,必须实现一个叫做Symbol.iterator的方法,该方法返回一个迭代器对象(Iterator),该迭代器对象有一个名为 next()的方法,这个方法被调用后会返回一个包含 done和 value 属性的对象。done 属性用于是否更多的元素需要返回,value 属性是下一个元素的值。每次 next()方法的调用都会返回下一个元素的值,调用完毕之后,done 返回 true 表示迭代已经结束。
怎么自己模拟一个迭代器?
简单的迭代器的实现:
function makeIterator(array) {let nextIndex = 0;return {next: function () {return nextIndex < array.length ?{ value: array[nextIndex++], done: false } :{ done: true };}};
}
// 使用迭代器遍历数组
let iterator = makeIterator([1, 2, 3]);
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {done: true}
上述代码中,makeIterator()
函数返回一个迭代器对象,其中包含一个 next() 方法。next() 方法每次被调用时,都会返回一个包含 value 和 done 两个属性的对象。其中,value 属性保存的是迭代器对象当前返回的值,done 属性表示迭代器对象是否已经遍历完所有元素。在上述示例中,调用 makeIterator([1, 2, 3])
返回一个迭代器对象,通过反复调用 next()
方法,可以依次访问数组 [1, 2, 3]
中的每一个元素。
什么是迭代器?
在ES6中,迭代器(Iterator)是一种可以通过遍历操作逐个访问集合中元素的机制。它是一种通用的接口和一组规范,可以通过实现附加到任何对象上,从而使得这些对象支持迭代操作。通俗地说,可以把迭代器看作是一种访问集合元素的方式,它提供了一种标准的遍历数据结构的方式。将其传统的理解方式放到JS中的常见数据类型,比如字符串、数组、Map等对象上,则可以通过 for…of 语句来进行遍历。
Iterator的作用?
- 为各种数据结构,提供一个统一的、简便的访问接口;
- 使得数据结构的成员能够按某种次序排列;
- ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of循环
ES6 规定,默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性,或者说,一个数据结构只要具有 Symbol.iterator 属性,就可以认为是“可遍历的”(iterable)。
总结:在 JavaScript 中,可迭代对象是指实现了Iterable 接口的对象,该接口包括一个默认的迭代器方法 Symbol.iterator()
,该方法返回一个迭代器对象(Iterator),该迭代器对象包含一个 next()
方法,用于返回序列中的下一个值。例如,数组、字符串、Map、Set 等数据结构都是可迭代对象。for...of 循环只能用于遍历实现了 Iterable 接口的对象,并且执行循环时会自动调用该对象的 Symbol.iterator()
方法获取迭代器对象。因此,对于无法返回迭代器对象的对象,for...of 循环是无法使用的。