js迭代器与生成器

news/2024/7/10 23:23:40 标签: javascript, es6

迭代器

背景

1.什么是迭代器

  • 从一个数据集合中按照一定的顺序,不断取出数据的过程

2.迭代和循环有什么区别?

  • 迭代强调的是依次去数据,并不保证取多少,也不保证所有的数据都要取完
  • 遍历:把整个数据依次的全部取出

3.迭代器

  • 对迭代过程的封装,在不同语言中有不同的表现形式,通常是一个对象。

4.迭代模式

  • 一种设计模式,用于统一迭代过程,并且规范了迭代器规格。
  • –迭代器具有得到下一个数据的能力
  • –迭代器具有判断是否还有后续数据的能力

JS中迭代器

JS规定

  • 如果一个对象具有 next(),并且该方法能够返回一个对象
    {value:值,done是否迭代完成}
    则认为该对象是一个迭代器

含义:

  • next()用于得到下一个数据
    返回一个对象
    value:下一个数据的值
    done:boolean 是否迭代完成

不能理解没关系,看了理论再看看案例,通过案例来理解理论

创建迭代器案例

由下面代码结合理论可知:迭代器就是执行next()方法来获取一个result对象,result对象内部有属性value:本次运行获得的值,done:是否可继续迭代 (done的值由代码可知,当i的值大于或等于数组的的长度,说明已经遍历到最后一个数字了,那么done就为true)。然后i自增,等到下次运行的next方法返回的对象中value就为数组的第二个值,done会继续判断是否为false。下面中的while就是通过不断执行next方法通过返回的result对象中的value来遍历每一个数

javascript">//利用迭代器循环打印数组的所有数
        const arr = [1,2,3,4,5,6,7,8,9];
        const iterator ={
            i:0,   //当前数据的下标
            next(){
                let result={
                    value:arr[this.i],
                    done:this.i >=arr.length,
                }
                this.i++;
                return result
            }
        }
        let data = iterator.next();
        while(!data.done){
            console.log(data.value);
            data = iterator.next();//重复书写的目的是让i自增
        }
        //最终打印出:1,2,3,4,5,6,7,8,9

通过函数来创建迭代器 ↓
其实原理都一样,只不过需要先执行这个函数来获取到迭代器

javascript">let arr = [1,3,5,7,9];
        // 创建一个迭代函数
        function createiterator(arr){
            let i = 0;
            return{
                next(){
                    let result = {
                        value:arr[i],
                        done:i>=arr.length
                    }
                    i++;
                    return result;
                }
            }
        }
        const itr1 = createiterator(arr);
        console.log(itr1.next());

可迭代协议

ES6中规定, 如果对象具有知名符号 symbol.iterator并且属性值是一个迭代器创建函数,则该对象是可以进行迭代的。

如图:可以看到,数组是具备这两个条件的,所以数组是可迭代对象:也就是说,我们可以不用创建迭代器,数组本身自带迭代器,通过属性调用就可以获得到它的迭代器了

除了数组也还有其他的可迭代对象。例如通过document.querySelectorAll()获取的标签集合也是一个可迭代对象,因为具备符号 symbol.iterator并且属性值是一个迭代器创建函数
在这里插入图片描述
可迭代对象可以通过隐式原型获取迭代器。

javascript">let arr = [1,2,3,4,5,6];
        //获取迭代器
        const iterator = arr[Symbol.iterator]();
        let result = iterator.next();
        while(!result.done){
            console.log(result.value);
            result = iterator.next();
        }
        //输出1,2,3,4,5,6

下图可以看到,纯对象就不是一个可迭代对象,它没有符号 symbol.iterator
在这里插入图片描述

for - of 循环

for - of用于遍历可迭代对象。

可以看到,简化了上面的代码。但条件是只能作用在可迭代对象上

 for(const item of iterator){
        item   //每次迭代得到的数组
        iterator //可迭代对象
    }
javascript">let arr = [1, 2, 3, 4, 5, 6];
        for(let item of arr){
            console.log(item);
        }
        //输出1,2,3,4,5,6

根据上面的可迭代协议可以知道,纯对象不是一个可迭代对象,所以无法使用for-of,但是我们可以通过给它创建一个符号将它变成可迭代对象,然后调用for-of

javascript">let obj = {
            name:"hc",
            age:18,
            [Symbol.iterator](){
                const keys = Object.keys(this);
                const Values =  Object.values(this);
                let i = 0;
                return {
                    next(){
                        const Name = keys[i];
                        const Vlue = Values[i]
                        const result = {
                            value:{
                                Name,
                                Vlue,
                            },
                            done:i>=keys.length
                        }
                        i++;
                        return result
                    }
                }

            }
        }
        for(let iter of obj){
            console.log(iter);
        }  

输出如下,但需要注意的是,我们创建的符号并没有被写入到隐式原型里面去(看红框框)
在这里插入图片描述

展开运算符和迭代对象

展开运算符可以作用于可迭代对象,这样我们就可以将可迭代对象转化为数组

javascript">        let obj = {
            name: "hc",
            age: 18,
            [Symbol.iterator]() {
                const keys = Object.keys(this);
                const Values = Object.values(this);
                let i = 0;
                return {
                    next() {
                        const Name = keys[i];
                        const Vlue = Values[i]
                        // const Value = this.Name;
                        const result = {
                            value: {
                                Name,
                                Vlue,
                            },
                            done: i >= keys.length
                        }
                        i++;
                        return result
                    }
                }

            }
        }
        let arr = [...obj];
        console.log(arr);

在这里插入图片描述
分析得出:在展开运算符解析对象的时候,此时的对象运行了一次next()方法。返回的值也是一个对象,然后赋值给arr。由于此对象中有两个键值对,故运行了两遍。

生成器

1.什么是生成器

  • 更加方便的编写迭代器
  • 生成器是一个通过 Generator函数来创建的对象
  • 生成器功能即是一个迭代器(因为可以通过生成器.next来进行迭代)
  • 同时又是一个可迭代对象(生成器拥有Symbol.iterator

2.如何去创建一个生成器

  • 生成器的创建,必须使用生成器函数 Generator function

3.如何去创建一个生成器函数

    <!-- 表示这是一个生成器函数  一定会返回一个生成器 -->
    function* show(){

    }

4.生成器函数内部是如何执行的

  • 生成器函数内部是为了给生成器的每次迭代提供数据。
  • 每次调用next方法 将导致生成器运行到 下一个 yield 关键字位置
  • yield:是一个关键字 ,他只能在生成器内部使用 表示,产生一个迭代数据

创建一个生成器

根据上面的理论,可以简化理解成给function后面加个* 那么这个函数便成了一个生成器。通过将生成器赋值给一个变量,然后调用next方法来达到迭代器的作用。

运行流程

遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。

javascript">        function* show(){
            console.log("第一次执行");
            yield 100000;
            console.log("第二次执行");
            yield 20;
        }
        let arr = show();
        console.log(arr.next());
        console.log(arr.next());

输出情况
在这里插入图片描述
也可以传参

javascript">	 	let arr = [1,3,5,7,9];
        let arr2 = [2,4,6,8,10];
        function* creatiterator(arr){
            for(let item of arr){
                yield item;
            }
        } 
        let item1 = creatiterator(arr);
        let item2 = creatiterator(arr2);
        console.log(item1.next());
        console.log(item2.next());

生成器中的return

由下面例子可知。当在生成器中遇见return时会提前强行将done的值变成true,提前结束迭代,并且return后面的值为最后一次有效迭代的值。

javascript">        function* show(){
            let num1 = "一袋米抗几楼"
            console.log("第一次执行");
            yield num1;
            console.log("第二次执行");
            yield 20;
            console.log("第二次执行");
            return "zyl真帅"
            yield 30;
            console.log("第二次执行");
            yield 40;
            console.log("第三次执行");
            return "zyl真帅"
        }
        let arr = show();
        console.log(arr.next());

执行结果
在这里插入图片描述

补充

javascript">function* t1(){
            yield function show(){
                // console.log(111);
                return 111;
            }
            yield "b"
        }
        function* t2(){
            yield* t1()
            yield "c"
            yield "d"
            yield "e"
        }  
        let test = t2();
        console.log(test.next());

输出情况

可以看出yield后面跟着的值可以是多样化的,并且,上述代码中,show函数里面return并没有终止迭代。说明如果return不是直接拦截的话。迭代是不会终止的
在这里插入图片描述


http://www.niftyadmin.cn/n/1570178.html

相关文章

python七段数码管绘制实验报告_Python入门基础:七段数码管绘制

原博文 2019-09-13 15:44 − 1.在学习Python的过程中&#xff0c;运用所学的一些基础知识&#xff0c;进行一些简单的编程&#xff0c;可以收获很多乐趣。在生活中&#xff0c;LED灯无处不在&#xff0c;荧幕显示的广告词&#xff0c;给我们呈现出动态的视觉效果。下面&#xf…

python文件之间的相互调用_python:关于py文件之间相互import的问题

问题背景调试脚本时&#xff0c;遇到一个问题&#xff1a;ImportError: cannot import name A from study_case.a (/Users/rchera/PycharmProjects/test/study_case/a.py)具体情况是这样婶儿的&#xff1a; 前些日子写了一个py文件&#xff0c;它的功能主要是创建数据(暂且称为…

js的属性提示符与存储器属性

属性提示符 Property Descriptor 属性描述符 这也是直接 对象名.属性 方式给对象添加一个属性的底层方法 Object.getOwnPropertyDescriptor(对象&#xff0c;属性名) 或Object.getOwnPropertyDescriptors&#xff08;对象&#xff09;可以得到一个属性的描述符 let obj {nam…

用eviews建立sarima模型_【十分钟计量经济学】Eviews估计方法总结

最小二乘法&#xff08;1&#xff09;普通最小二乘估计&#xff08;OLS&#xff09;&#xff1a;这是使用的最为普遍的模型&#xff0c;基本原理就是估计残差平方和最小化&#xff0c;不予赘述。&#xff08;2&#xff09;加权最小二乘估计&#xff08;WLS&#xff09; Eviews路…

js的Set和Map集合

Set 作用&#xff1a;用于存放不重复的数据 创建&#xff1a; let set1 new Set(); //创建一个没有任何内容的set集合let set2 new Set("LOLFPXIGRNGSN");//具有初始化数值的set集合可以看到打印出来的结果没有重复的字母 属性&#xff08;由于属性有很多&…

qq机器人源码_手把手教你搭建自己的小程序机器人客服

今天给大家讲一讲微信的新功能&#xff0c;微信对话开放平台的小程序对接及使用拓展方法&#xff01;相当于有了一个手机版某爱同学了&#xff0c;功能真的不可谓不强大&#xff01;还自带游戏功能&#xff0c;之后甚至可以根据游戏最后得分获得某奖励&#xff0c;无限YY中~PS&…

vue基础和它的基础指令

vue基础使用 创建方法 其中的el 类型 是一个字符串全称 element&#xff08;元素&#xff09;作用 配置控制的元素—表示vue要控制的区域&#xff0c;值为CSS选择器 其中的data 类型 对象作用 存放要用到的数据&#xff0c;数据为响应式的。 let vm new Vue({el:"#s…