IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> ES6-迭代器、生成器 -> 正文阅读

[JavaScript知识库]ES6-迭代器、生成器

迭代器

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

ES6迭代器的使用

  • ES6创造了一种新的遍历命令for...of循环,lterator接口主要供 for...of消费
  • 原生具备iterator接口的数据(可用for of遍历):
    • Array
    • Arguments
    • Set
    • Map
    • String
    • TypedArray
    • NodeList
      具备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:

log.csdnimg.cn/c6f3f2f96ab24ca9aef62c3e19179d94.png)

代码:

<!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>Document</title>
</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>Document</title>
</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>Document</title>
</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>

输出;
在这里插入图片描述

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 17:32:01  更:2022-05-18 17:32:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:51:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码