• 迭代器与生成器


    迭代器是一种接口,也可以说是一种规范。它提供了一种统一的遍历数据的方法for-of。我们都知道数组、集合、对象都有自己的循环遍历方法。

    支持了迭代器的数据结构才能使用for-of循环。迭代器可以提供统一的遍历数据的方式,只要在想要遍历的数据结构中添加一个支持迭代器的属性即可。这个属性写法是这样的:

    1 const obj = {
    2     [Symbol.iterator]:function(){}
    3 }

    Symbol.iterator属性对应一个函数,执行后返回当前对象的遍历器对象。

    在JS中,默认支持迭代器的结构有:

    • Array
    • Map
    • Set
    • String
    • TypedArray
    • 函数的 arguments 对象
    • NodeList 对象

     显然自定义对象不包含在其中,自然也不能使用for-of:

     1         let obj ={
     2             name:'郑大侠',
     3             age:'22',
     4             gender:'男',
     5             introduce:function(){
     6                 console.log('我是'+this.name);
     7             }
     8 
     9         }
    10 
    11         for(let attr of obj){
    12             console.log(attr);  //Uncaught TypeError: obj is not iterable
    13         }

    数组就可以:

    1         let arr=[1,2,3]
    2         for(let a of arr){
    3             console.log(a); // 1  2  3
    4         }

    迭代器属性[Symbol.iterator]可执行来返回一个对象

    该属性返回的对象上有next()方法,

    迭代器的遍历方法是首先获得一个迭代器的指针,初始时该指针指向第一条数据之前。接着通过调用next方法,改变指针的指向,让其指向下一条数据。每一次的next都会返回一个对象,该对象有两个属性。其中value代表想要获取的数据,done是个布尔值,false表示当前指针指向的数据有值。true表示遍历已经结束。
    以含有迭代器属性的数组为例:    
    1         let arr=[1,2,3]
    2         let a = arr[Symbol.iterator]()
    3         console.log(a.next());
    4         console.log(a.next());
    5         console.log(a.next());

     要使得自定义对象也可以迭代遍历,可以通过手动添加迭代器完成:

     1         let obj ={
     2             name:'郑大侠',
     3             age:'22',
     4             gender:'男',
     5             introduce:function(){
     6                 console.log('我是'+this.name);
     7             },
     8             [Symbol.iterator]:function(){
     9                 let i =0
    10                 // 获取当前对象并存入一个数组里
    11                 let keys = Object.keys(this)
    12                 // 返回一个next方法
    13                 return {
    14                     next(){
    15                         return{
    16                             value:keys[i++],    //每次遍历得到第i个属性
    17                             done:i>keys.length  //遍历完成则返回false
    18                         }
    19                     }
    20                 }
    21             }
    22         }
    23         let o = obj[Symbol.iterator]()
    24         console.log(o.next());
    25         console.log(o.next());
    26         console.log(o.next());
    27         console.log(o.next());
    28         // 完成
    29         for(let attr of obj){
    30             console.log(attr);  
    31         }

    生成器(Generator)

    Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。调用它返回迭代器对象

    形式上的定义:

    1 function* say(){}  //这个”*”只能写在function关键字的后面。
    2 const say = function*(){}  
    普通函数在调用后,必然开始执行该函数,直到函数执行完或遇到return为止。中途是不可能暂停的。但是生成器函数则不一样,它可以通过yield关键字将函数的执行挂起,或者理解成暂停。它的外部在通过调用next方法,让函数继续执行,直到遇到下一个yield,或函数执行完毕
     
    调用say函数,这句和普通函数的调用没什么区别。但是此时say函数并没有执行,而是返回了一个该生成器的迭代器对象。接下来就和之前一样,执行next方法,say函数执行,当遇到yield时,函数被挂起,并返回一个对象对象中包含value属性,它的值是yield后面跟着的数据。并且done的值为false。再次执行next,函数又被激活,并继续往下执行,直到遇到下一个yield。当所有的yield都执行完了,再次调用next时得到的value就是undefined,done的值为true。
     
     1         function* say() {
     2             yield "开始";
     3             yield "执行中";
     4             yield "结束";
     5         }
     6         let it = say();         // 调用say方法,得到一个迭代器
     7         console.log(it.next()); // { value: '开始', done: false }
     8         console.log(it.next()); // { value: '执行中', done: false }
     9         console.log(it.next()); // { value: '结束', done: false }
    10         console.log(it.next()); // { value: undefined, done: true }

    它的yield,其实就是next方法执行后挂起的地方,并得到你返回的数据。

    那么这个生成器有什么用呢?它的yield关键字可以将执行的代码挂起,外部通过next方法让它继续运行,这和异步操作的原理非常类似。




     



    参考:https://zhuanlan.zhihu.com/p/66593213


  • 相关阅读:
    2020寒假简记
    感知神经网络模型与学习算法
    信息检索模型与评估
    Diffie-Hellman密钥交换
    RSA密码体制
    MySQL基准测试(benchmark)
    MySQL数据引擎
    MySQL 多版本并发控制(MVCC)
    MySQL事务管理
    利用dotnet restore 导入本地 .nupkg 包
  • 原文地址:https://www.cnblogs.com/zxf906/p/15335195.html
Copyright © 2020-2023  润新知