迭代器与生成器
目录
Iterator 的作用
Iterator 的遍历过程
Symbol.iterator方法
实现iterator接口的自定义类示例
Generator函数
迭代器对象的next方法的运行逻辑
迭代器对象除了具有next方法,还可以具有return方法。
Iterator 的作用
为各种数据结构,提供一个统一的、简便的访问接口。
使得数据结构的成员能够按某种次序排列。
任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。Iterator 接口约定对象必须具备Symbol.iterator方法,且该方法返回一个迭代器对象。
Iterator 的遍历过程
创建一个指针对象(迭代器),指向当前数据结构的起始位置。 也就是说,迭代器对象本质上,就是一个指针对象。该对象必定有一个名为next的方法。
第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员;第二次调用指针对象的next方法,指针就指向数据结构的第二个成员;不断调用指针对象的next方法,直到它指向数据结构的结束位置。
Symbol.iterator方法
默认的 Iterator 接口部署在数据结构的Symbol.iterator方法。也就是说,一个数据结构只要具有Symbol.iterator方法,就可以认为是“可遍历的”(iterable)。
原生具备 Iterator 接口的数据结构:
- Array
- Map
- Set
- String
- TypedArray(类型化的数组)
- 函数的 arguments 对象
- NodeList 对象
let arr = ["a", "b", "c"];
let iter = arr[Symbol.iterator]();
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
一个对象如果要具备可被for...of调用的 Iterator 接口,就必须在Symbol.iterator上部署生成迭代器对象的方法。
迭代器对象必须具备next方法。next方法必须返回一个具备value和done的对象。
{value: undefined, done: true}
value为每次迭代的值,迭代结束时该值为undefined。
done为布尔值,表示迭代是否结束,结束为true,否则为false。
实现iterator接口的自定义类示例
class Rander {constructor(start, stop, step) {this.start = start;this.stop = stop;this.step = step;}[Symbol.iterator]() {let range = this;return {next() {let value = range.value;if (value < range.stop) {range.value += range.step;return { done: false, value: value };}return { done: true, value: undefined };},};}
}
function range(start, stop, step = 1) {return new Rander(start, stop, step);
}
for (let i of range(0, 9, 2)) {console.log(i);
}
let num = [...range(0, 9, 2)];
console.log(num);
Generator函数
生成器函数是用来产生一个生成器对象的。定义生成器函数需要使用*。
通过Generator函数实现Iterator 接口迭代。
let obj = {
name1: "Tom",
name2: "Jerry",
name3: "Mickey",
name4: "Miney",
*[Symbol.iterator]() {
yield this.name1;
yield this.name2;
yield this.name3;
},
};
console.log(obj[Symbol.iterator]().next());
console.log([...obj]);
for (let k of obj) {
console.log(k);
}
由于 Generator 函数返回的迭 代器对象,只有调用next方法才 会遍历下一个内部状态,所以其实 提供了一种可以暂停执行的函数。 yield表达式就是暂停标志。
迭代器对象的next方法的运行逻辑
- 遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值作为返回的对象的value属性值。
- 下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
- 如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值作为返回的对象的value属性值。
- 如果该函数没有return语句(即没有返回值),则返回的对象的value属性值为undefined。
迭代器对象除了具有next方法,还可以具有return方法。
如果for...of循环提前退出(通常是因为出错,或者有break语句),就会调用return方法。如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return方法。