红宝石阅读笔记

第七章 迭代器与生成器

7.2 迭代器模式

迭代协议具体分为两个协议:可迭代协议和迭代器协议。

可迭代协议:规定对象是否可迭代-->对象属性上必须有一个Symbol.iterator属性,[Symbol.iterator] :一个无参数的函数(普通函数或者生成器函数),其返回值为一个符合迭代器协议的对象。

迭代器协议:规定了一个对象是否是迭代器:按照规定实现next(),具体查看MDN文档。

很多内置类型都实现了 Iterable 接口(也就是实现了可迭代协议)

  1. 字符串
  2. 数组
  3. 映射
  4. 集合
  5.  arguments 对象
  6. NodeList DOM 集合类型

原生语言特性其实接收可迭代对象(它们会先调用[Symbol.iterator]方法获取迭代器):

  1. for-of 循环
  2.  数组解构
  3. 扩展操作符
  4. Array.from()
  5. 创建集合
  6. 创建映射
  7. Promise.all()接收由期约组成的可迭代对象
  8. Promise.race()接收由期约组成的可迭代对象
  9. yield*操作符,在生成器中使用

7.3 生成器

生成器函数(也就是*函数)产生生成器对象,生成器对象也实现了可迭代协议。

红宝石阅读笔记_第1张图片

乍一看理解,仔细想没理解,然后自己让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;
}

//TODO持续更新

你可能感兴趣的:(Js,es6,笔记,javascript)