我只是以当前的认知去看这本书,下面是我觉得有必要记录的点,也算是自己对每一章节内容的浓缩总结!
目录
第七章 迭代器与生成器
7.2 迭代器模式
迭代协议具体分为两个协议:可迭代协议和迭代器协议。
可迭代协议:规定对象是否可迭代-->对象属性上必须有一个Symbol.iterator属性,[Symbol.iterator] :一个无参数的函数(普通函数或者生成器函数),其返回值为一个符合迭代器协议的对象。
迭代器协议:规定了一个对象是否是迭代器:按照规定实现next(),具体查看MDN文档。
很多内置类型都实现了 Iterable 接口(也就是实现了可迭代协议)
- 字符串
- 数组
- 映射
- 集合
- arguments 对象
- NodeList 等 DOM 集合类型
原生语言特性其实接收可迭代对象(它们会先调用[Symbol.iterator]方法获取迭代器):
- for-of 循环
- 数组解构
- 扩展操作符
- Array.from()
- 创建集合
- 创建映射
- Promise.all()接收由期约组成的可迭代对象
- Promise.race()接收由期约组成的可迭代对象
- yield*操作符,在生成器中使用
7.3 生成器
生成器函数(也就是*函数)产生生成器对象,生成器对象也实现了可迭代协议。
乍一看理解,仔细想没理解,然后自己让n=2,还原nTimes,等价于
function* nTimes() {
if (true) {
yield* (function* A() {
if (true) {
yield* (function* B() { })();
yield 0;
}
})();
yield 1;
}
}
最难理解的是n=0的时候
yield* (function* B() { })();
yield*后面必须跟一个可迭代对象,*号函数正好返回一个可迭代对象,但是当这个可迭代对象没有可以迭代的操作(也就是内部没有yield表达式)时候,会被忽略(yield* (function* B() { })(); 被当成一个同步代码在执行),所以应该执行yield 0;
let aa = nTimes();
console.log(aa.next());
console.log(aa.next());
所以第一次打印出{ value: 0, done: false }。
也就是
(function* A() {
if (true) {
yield* (function* B() { })();
yield 0;
}
})()
执行完毕。
所以第二次执行的时候就相当于在执行yield 1;,所以打印出来就是{ value: 1, done: false }。
所以yield* nTimes(3 - 1) 等价于
yield* [yield 2 - 1, yield 1 - 1];
nTimes(3) 等价于nTimes3()
function* nTimes(n) {
if (n > 0) {
yield* nTimes(n - 1);
yield n - 1;
}
}
function* nTimes3() {
yield* [yield 2 - 1, yield 1 - 1];
yield 3 - 1;
}