ES6迭代器和生成器

1. 迭代器

1. 定义:

迭代器就是一种机制。它是一种接口,为各种不同的数据结构提 供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

2.   原生具备 iterator 接口的数据 ( 可用 for of 遍历【ES6 创造了一种新的遍历命令 for...of 循环, Iterator 接口主要供 for...of 消费】)
  • Array
  • Arguments
  • Set ( new Set( ) )
  • Map( new Map( ) )
  • String
  • TypedArray
  • NodeList
3.  工作原理
  • 创建一个指针对象,指向当前数据结构的起始位置
  • 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
  • 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
  • 每调用 next 方法返回一个包含 value done 属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
​
<!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>
    // 声明一个数组
    const arr = ['ansk', 'youzi', 'yusheng'];
    // for of 遍历
    for (let v of arr) {
      console.log(v); // ansk  youzi yusheng , 如果是 in 打印 0 1 2
    }
    let iterator = arr[Symbol.iterator]();
    // 调用对象的next方法
    console.log(iterator.next()); // {value: 'ansk', done: false}
    console.log(iterator.next()); // {value: 'youzi', done: false}
    console.log(iterator.next()); // {value: 'yusheng', done: false}  done为true表示遍历已经完成
  </script>
</body>

</html>

​

 自定义迭代器,遍历数据:

<!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>自定义遍历数据</title>
</head>

<body>
  <script>
    const obj = {
      name: 'yusheng',
      age: 28,
      stus: [
        'youzi',
        'ansk',
        'goat',
        'fanyu'
      ],
      [Symbol.iterator]() {
        let index = 0;
        let _this = this;
        return {
          next: function () {
            if (index < _this.stus.length) {
              const result = { value: _this.stus[index], done: false };
              index++;
              return result;
            } else { // 执行完毕,value 值为 undefined 且 done 值为 true
              return { value: undefined, done: true }
            }
          }
        }
      }
    }
    // 遍历这个对象 for of
    for (let v of obj) {
      console.log(v);
    }
  </script>
</body>

</html>

2. 生成器

1.  * 的位置没有限制
2.   生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值
3. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
4. next 方法可以传递实参,作为 yield 语句的返回值
<!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>生成器</title>
</head>

<body>
  <script>
    // 生成器其实就是一个特殊的函数
    // 异步编程     回调函数
    // yield 函数代码的分隔符,把代码分成几块
    function* gen() {
      console.log(111);
      yield 'hello';
      console.log(222);
      yield 'hi';
      console.log(333);
      yield '你好';
      console.log(444);
    }
    let iterator = gen();
    iterator.next(); // 111
    iterator.next(); // 222
    iterator.next(); // 333
    iterator.next(); // 444

    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
    // 111
    // {value: 'hello', done: false}
    // 222
    // {value: 'hi', done: false}
    // 333
    // {value: '你好', done: false}
    // 444
    // {value: undefined, done: true}

    for (let v of gen()) {
      console.log(v); // 打印 yield 后面的值
    }
  </script>
</body>

</html>

生成器传参:

<!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>生成器函数参数</title>
</head>

<body>
  <script>

    function* gen(arg) {
      console.log(arg);
      let one = yield 111;
      console.log(one); // BBB
      let two = yield 222;
      console.log(two); // CCC
      let three = yield 333;
      console.log(three); // DDD
    }

    // 执行获取迭代器对象
    let iterator = gen('AAA');
    console.log(iterator.next());
    // next 方法可以传入实参
    console.log(iterator.next('BBB'));// 第2次调用next()传入的实参将作为第1个yield返回的结果
    console.log(iterator.next('CCC'));// 第3次调用next()传入的实参将作为第2个yield返回的结果
    console.log(iterator.next('DDD'));// 第4次调用next()传入的实参将作为第3个yield返回的结果
  </script>
</body>

</html>

 

3. 练习

生成器练习:

要求: 1 s 后控制台输出 111,2 s 后控制台输出 222, 3 s 后控制台输出 333

<!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>生成器函数实例</title>
</head>

<body>
  <script>
    // 异步编程 文件操作、网络操作(ajax,request)、数据库操作
    // 1s后控制台输出111 2s后控制台输出222 3s后控制台输出333
    // 之前的写法:
    setTimeout(() => { // 回调地狱
      console.log(111);
      setTimeout(() => {
        console.log(222);
        setTimeout(() => {
          console.log(333);
        }, 3000);
      }, 2000);
    }, 1000);

    // ES6 写法:
    function one() {
      setTimeout(() => {
        console.log(111);
        iterator.next();
      }, 1000);
    }
    function two() {
      setTimeout(() => {
        console.log(222);
        iterator.next();
      }, 2000)
    }
    function three() {
      setTimeout(() => {
        console.log(333);
        iterator.next();
      }, 3000)
    }
    function* gen() {
      yield one();
      yield two();
      yield three();
    }
    // 调用生成器函数
    let iterator = gen();
    iterator.next();
  </script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值