2020-09-07 简析Iterator遍历器、Generator函数、Async函数

Iterator遍历器:

        // 一种数据结构只要部署了 Iterator 接口,我们就称这种数据结构是“可遍历的”,
        // ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,
        // 一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”
        // 原生具备 Iterator 接口的数据结构如下:
            // Array
            // Map
            // Set
            // String
            // TypedArray
            // 函数的 arguments 对象
            // NodeList 对象

        var m = new Map();
        m.set("name","zs");
        m.set("age",100);
        for(let item of m){
            console.log(item);//[key,value];
        }
        // 任意一个对象的Symbol.iterator属性等于该对象的遍历器生成函数,调用该函数返回遍历器对象(指针)
        var result=m[Symbol.iterator]();
        console.log(result); //MapIterator {"name" => "zs", "age" => 100}
        console.log(result.next()); //{value: Array(2), done: false}
        console.log(result.next()); //{value: Array(2), done: false}
        console.log(result.next()); //{value: undefined, done: true}  
        // 注意:对于遍历器对象来说,done: false和value: undefined属性都是可以省略的  

Generator函数:

        // Generator 函数是一个状态机,封装了多个内部状态。
        // 执行 Generator 函数会返回一个遍历器指针对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。

        // 调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,
        // 就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;
        // done属性是一个布尔值,表示是否遍历结束。

        function* fn() {
            console.log(1);
            var y1 = yield "y1";  // y1的值是next()方法的传递的实参,每个next()的实参是传给上一个yield变量
            console.log(y1);    // 2
            var y2 = yield "y2";
            console.log(y2);    // 3
            return "y3";        //generator函数不承认return返回值   
            console.log("y4");  //不执行,说明return还是能结束函数的执行
            
        }

        // 尽量别用表达式创建generator函数!
        // var fn=function* (){
        //     console.log(1);
        //     var y1=yield "y1";
        //     console.log(y1);
        //     var y2=yield "y2";
        //     console.log(y2);
        //     return "y3"; 
        // }

        var fn = fn();  // 此处调用并不执行函数fn内部代码(普通函数是会执行的),只是生成了遍历器对象,只有在调用next()时才会执行内部代码
        console.log(fn);  // fn {<suspended>}

        // next如果带参数,这个参数代表上一个yield的返回值
        console.log(fn.next(1));  // 开始执行函数内部代码,直到遇到yield就停止执行  {value: "y1", done: false}
        console.log(fn.next(2));  // 执行第一个yield之后到第二个yield之间的代码    {value: "y2", done: false}
        console.log(fn.next(3));  // {value: "y3", done: true}                  done是true,说明函数不承认这个返回值
        console.log(fn.next(4));  // {value: undefined, done: true}             找不到返回值了,done就是true

Async函数:

        // - async是generator 语法糖:
        // async函数返回一个 Promise 对象。async函数内部return语句返回的值,会成为then方法回调函数的参数。
        // - async 函数中,用await 等待一个promise成功状态的执行 ,同时可以获取到promise的返回值;
        // - await 下面的代码直接使用返回值;
        // - 保证了 代码的上下顺序就是执行顺序


        async function fn() {
            // try {无异常执行代码} ctach{异常情况时执行的代码}
            try {
                // await等待promise对象状态为resolve时执行(从回调地狱到promise链式再到符合正常习惯的一行一行代码)
                // 定义变量获取返回的数据(如无await,不能直接用变量获取异步数据)
                var data1 = await $.ajax("http://10.10.22.62:3000/api/getinfo"); 
                var data2 = await $.ajax("http://10.10.22.62:3000/api/getmatch/" + data1.info[0].cardid);

                // 显示数据到页面中
                $("body").html(`姓名:${data1.info[0].name} 编号:${data1.info[0].cardid} 双方信息:${data2.info.match.join("VS")}`);
            
            } catch (err) {
                alert("没有获取到信息");
            }
        }
        fn(); // 调用函数

相关原理及相互的关系:


2021.08.23_17.00.14.jpg

如图所示:如果一个对象不具备iterator接口,我们又需要遍历它时可以给这个对象添加遍历器生成函数,原理见图解。

     对象的iterator接口部署在 对象的Symbol.iterator属性上 —》

    该属性实质上相当于一个遍历器生成函数 —》

    调用该属性可以返回一个遍历器指针对象 —》

   调用该指针对象的next()方法可以遍历对象 —》

   对于不具备iterator接口的对象,可以给它添加一个Symbol.iterator属性,属性值为一个遍历器生成函数,那么它就可以被遍历了。。(Generator函数就是这样的遍历器生成函数)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容