红宝石4 第七章 迭代器和生成器

113 阅读1分钟
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 本章学习资源来自于MDN
      // function* 这种声明方式(function关键字后跟一个星号)会定义一个生成器函数 (generator function),它返回一个  Generator  对象。
      function* generator(i) {
        yield i;
        yield i + 10;
      }
      const gen = generator(10);
      console.log("function*1 ", gen.next().value); //10
      console.log("function*2 ", gen.next().value); //20

      //迭代器
      function makeRangIterator(start = 0, end = Infinity, step = 1) {
        let nextIndex = start;
        let iteratorCount = 0;

        const rangIterator = {
          next: function () {
            let result;
            if (nextIndex < end) {
              result = { value: nextIndex, done: false };
              nextIndex += step;
              iteratorCount++;
              return result;
            }
            return { value: iteratorCount, done: true };
          },
        };
        return rangIterator;
      }

      let it = makeRangIterator(1, 5, 1); //(开始值,范围值,加数值)

      let result = it.next();
      while (!result.done) {
        console.log(result.value); //1,2,3,4
        result = it.next();
      }
      console.log("元素数量:", result.value); //4

      //   生成器函数
      // 生成器函数使用 function*语法编写
      function* makeRangIterator(start = 0, end = infinity, step = 1) {
        for (let i = start; i < end; i += step) {
          yield i;
        }
      }
      let a = makeRangIterator(1, 10, 2);
      for (value of a) {
        console.log("生成器函数", value);
      }

      // 自定义的可迭代对象
      let myIterable = {
        *[Symbol.iterator]() {
          yield 1;
          yield 2;
          yield 3;
        },
      };

      for (let value of myIterable) {
        console.log("value", value);
      }
      console.log("[...myIterable]", [...myIterable]);
      // 用于可迭代对象的语法
      for (let value of ["a", "b", "c"]) {
        console.log("用于可迭代对象的语法", value);
      }
      console.log("[...'abc']:", [..."abc"]);
      function* gen2() {
        yield* ["a", "b", "c"];
      }
      console.log(gen2().next());
      [a, b, c] = new Set(["a", "b", "c"]);
      console.log("a:", a);
      // 高级生成器
      function* fibonacci() {
        var fn1 = 0;
        var fn2 = 1;
        while (true) {
          var current = fn1;
          fn1 = fn2;
          fn2 = current + fn1;
          var reset = yield current;
          if (reset) {
            fn1 = 0;
            fn2 = 1;
          }
        }
      }

      var sequence = fibonacci();
      var i2 = 8;
      for (let i1 = 0; i1 < i2; i1++) {
        if (i1 < i2) {
          console.log(sequence.next().value);
        }
      }

      //7.4 小结
      // 迭代是一种所有编程语言中都可以看到的模式。ECMAScript 6 正式支持迭代模式并引入了两个新的
      // 语言特性:迭代器和生成器。
      // 迭代器是一个可以由任意对象实现的接口,支持连续获取对象产出的每一个值。任何实现 Iterable
      // 接口的对象都有一个 Symbol.iterator 属性,这个属性引用默认迭代器。默认迭代器就像一个迭代器
      // 工厂,也就是一个函数,调用之后会产生一个实现 Iterator 接口的对象。
      // 迭代器必须通过连续调用 next()方法才能连续取得值,这个方法返回一个 IteratorObject。这
      // 个对象包含一个 done 属性和一个 value 属性。前者是一个布尔值,表示是否还有更多值可以访问;后
      // 者包含迭代器返回的当前值。这个接口可以通过手动反复调用 next()方法来消费,也可以通过原生消
      // 费者,比如 for-of 循环来自动消费。
      // 生成器是一种特殊的函数,调用之后会返回一个生成器对象。生成器对象实现了 Iterable 接口,
      // 因此可用在任何消费可迭代对象的地方。生成器的独特之处在于支持 yield 关键字,这个关键字能够
      // 暂停执行生成器函数。使用 yield 关键字还可以通过 next()方法接收输入和产生输出。在加上星号之
      // 后,yield 关键字可以将跟在它后面的可迭代对象序列化为一连串值。
    </script>
  </body>
</html>