ES6-迭代器、生成器

ES6-迭代器、生成器,第1张

文章目录 迭代器ES6迭代器的使用ES6迭代器的原理迭代器的应用——自定义遍历数据 生成器生成器函数声明格式调用格式yield 生成器的函数参数生成器的异步编程定时器异步 *** 作异步获取数据

迭代器

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

ES6迭代器的使用 ES6创造了一种新的遍历命令for...of循环,lterator接口主要供 for...of消费原生具备iterator接口的数据(可用for of遍历): ArrayArgumentsSetMapStringTypedArrayNodeList
具备iterator接口就是指具有 Symbol.iterator这个属性

eg:

        const xiyou =['唐僧','孙悟空','猪八戒','沙僧']

        // for ... of 遍历数组:保存的是值
        for(let v of xiyou){
            console.log(v)
        }
        
        // for ... in 遍历数组:保存的是下标
        for(let v in xiyou){
            console.log(v)
        }

        console.log(xiyou)

输出:

ES6迭代器的原理

数组之所以能够使用迭代器遍历是因为数组中有 Symbol.iterator这个属性,他的值是一个函数。
获取该函数

        const xiyou =['唐僧','孙悟空','猪八戒','沙僧']
        let iterator = xiyou[Symbol.iterator]()
        console.log(iterator)


有next方法。

迭代器工作原理:

第一次调用对象的next方法,指针自动指向数据结构的第一个成员接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员每调用next方法返回一个包含value和 done属性的对象

即迭代器的实现原理就是:

        const xiyou =['唐僧','孙悟空','猪八戒','沙僧']
        let iterator = xiyou[Symbol.iterator]()
        console.log(iterator.next())
        console.log(iterator.next())
        console.log(iterator.next())
        console.log(iterator.next())
        console.log(iterator.next())

输出:

迭代器的应用——自定义遍历数据

如果想要便利的对象没有Symbol.iterator属性,可以自定义该属性进行遍历
eg:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
head>
<body>

    <script>
    const banji = {
        name:'终极一班',
        stus:[
            'xiaoming',
            'xiaohong',
            'xiaoli',
            'xiaozhang'
        ],
        [Symbol.iterator](){
            // 索引变量
            let index = 0;
            let _this = this;
            return {
            //按照迭代器的遍历规则写出next函数
                next:function(){
                    if(index <_this.stus.length){
                        const result = {value:_this.stus[index],done:false}
                        index++;
                        return result
                    }else{
                        return {value:undefined,done:true}
                    }
                }
            }
        }
    }

    // 使用for of 遍历对象,且结果是stus的内容
    for( let v of banji){
        console.log(v)
    }

    script>    
body>
html>

生成器

生成器是一个函数,生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
之前实现异步编程使用的都是回调函数(回调函数:我们编写的函数,浏览器调用)。

生成器函数 声明格式
        function * 函数名(){      
        }

eg:

        function * gen(){
           console.log('hello generator')
        }
        console.log(gen())

输出:

没有输出hello generator,并且具有next方法,这是一个迭代器函数

调用格式

所以正确的调用方式:(调用next方法)

        function * gen(){
           console.log('hello generator')
        }
        let iterator = gen()
        iterator.next()

输出:

yield

yield是函数代码的分隔符,生成器函数中可以使用yield来分隔函数。
这时调用一个iterator.next()就执行一段被yield分割的代码。

eg:

代码:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
head>
<body>
    <script>
        function * gen(){
           console.log('一只没有耳朵')
           yield '1';
           console.log('一只没有尾巴')
           yield '2';
           console.log('真奇怪')
           yield '3';
           console.log('真奇怪')
        }
        let iterator = gen()
        iterator.next()
        iterator.next()
        iterator.next()
        iterator.next()
        
    script>
body>
html>

执行如下语句:

        let iterator = gen()
        console.log(iterator.next())
        console.log(iterator.next())
        console.log(iterator.next())
        console.log(iterator.next())

输出:

发现这是一个迭代器可以直接使用for of:

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
head>
<body>
    <script>
        function * gen(){
           console.log('一只没有耳朵')
           yield '1';
           console.log('一只没有尾巴')
           yield '2';
           console.log('真奇怪')
           yield '3';
           console.log('真奇怪')
        }
        for(let v of gen()){   
        }
        console.log('--------------------------')

        for(let v of gen()){ 
            console.log(v)
        }
        
    script>
body>
html>

生成器的函数参数

可以直接给生成器函数传参,
next()方法可以传入实参,该实参将作为上一个yield的返回结果.
EG:

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>Documenttitle>
head>
<body>
    <script>
        function * gen(arg){
            console.log(arg)
            let first = yield 111
            console.log(first)
            let second = yield 222
            console.log(second)
            let third = yield 333
            console.log(third)
        }

        let iterator = gen('AAA')
        console.log(iterator.next())
        // next()方法可以传入实参,该实参将作为上一个yield的返回结果
        console.log(iterator.next('BBB'))
        console.log(iterator.next('CCC'))
        console.log(iterator.next('DDD'))
    script>
body>
html>

输出:

生成器的异步编程

js是一个单线程的,所以很多js *** 作都是异步的,如:
文件 *** 作、网络 *** 作(ajax, request)、数据库 *** 作

定时器异步 *** 作

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

定时器实现:
    <script>
        setTimeout(()=>{
            console.log(111);
            setTimeout(()=>{
                console.log(222);
                setTimeout(()=>{
                    console.log(333);    
                },3000)    
            },2000)    
        },1000)
    </script>

(箭头函数时回调函数的一种)
通过回调里面套回调,不停的回调来实现异步 *** 作,这就出现了回调地狱。

生成器函数实现异步
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>Documenttitle>
head>
<body>
    <script>
        // setTimeout(()=>{
        //     console.log(111);
        //     setTimeout(()=>{
        //         console.log(222);
        //         setTimeout(()=>{
        //             console.log(333);    
        //         },3000)    
        //     },2000)    
        // },1000)

        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>
异步获取数据

需求:依次获取用户数据、订单数据、商品数据

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>Documenttitle>
head>
<body>
    <script>

        function getUsers(){
           setTimeout(()=>{
               let data = '用户数据'
               // 调用next,并将数据传入,那么该数据将作为第一个yield的返回结果
               iterator.next(data)
           },1000)
        }
        function getOrders(){
           setTimeout(()=>{
               let data = '订单数据'
               iterator.next(data)
           },1000)
        }
        function getGoods(){
           setTimeout(()=>{
               let data = '商品数据'
               iterator.next(data)
           },1000)
        }

        function * gen(){
           let users = yield getUsers();
           console.log(users)
           let orders = yield getOrders()
           console.log(orders)  
           let goods = yield getGoods()
           console.log(goods)
        }

        // 调用生成器函数
        let iterator=gen()
        iterator.next()

    script>
    
body>
html>

输出;

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/939455.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-17
下一篇2022-05-17

发表评论

登录后才能评论

评论列表(0条)

    保存