可迭代(Iterable)对象是数组的泛化。这个概念是说任何对象都可以被定制为可在for..of循环中使用的对象。
数组是可迭代的。但不仅仅是数组。很多其他内建对象也都是可迭代的。例如字符串也是可迭代的。
如果从技术上讲,对象不是数组,而是表示某物的集合(列表,集合),for..of是一个能够遍历它的很好的语法,因此,让我们来看看如何使其发挥作用。
通过自己创建一个对象,我们就可以轻松地掌握可迭代的概念。
例如,我们有一个对象,它并不是数组,但是看上去很适合使用for..of循环。
比如一个range对象,它代表了一个数字区间:
let range = { from: 1, to: 5 }; // 我们希望 for..of 这样运行: // for(let num of range) ... num=1,2,3,4,5
为了让range对象可迭代(也就让for..of可以运行)我们需要为对象添加一个名为Symbol.iterator的方法(一个专门用于使对象可迭代的内置 symbol)。
当for..of循环启动时,它会调用这个方法(如果没找到,就会报错)。这个方法必须返回一个迭代器(iterator)—— 一个有next方法的对象。从此开始,for..of仅适用于这个被返回的对象。当for..of循环希望取得下一个数值,它就调用这个对象的next()方法。next()方法返回的结果的格式必须是,当done=true时,表示迭代结束,否则value是下一个值。
这是带有注释的range的完整实现:
let range = { from: 1, to: 5 }; // 1. for..of 调用首先会调用这个: range[Symbol.iterator] = function() { // ……它返回迭代器对象(iterator object): // 2. 接下来,for..of 仅与此迭代器一起工作,要求它提供下一个值 return { current: this.from, last: this.to, // 3. next() 在for..of 的每一轮循环迭代中被调用 next() { // 4. 它将会返回 {done:.., value :...} 格式的对象 if (this.current