ES6_迭代器和生成器

本文深入探讨了JavaScript中的迭代器接口及其在数组、字符串和自定义对象中的应用。介绍了迭代器如何使数据结构能够遍历,以及如何手动实现迭代器。接着,文章阐述了生成器的概念,它是一种可以暂停和恢复执行的特殊函数,通过yield关键字实现数据的产出。生成器在迭代器中的应用使得复杂的数据处理变得更为灵活。最后,展示了如何使用生成器实现对象的迭代器接口,使其能被for...of...循环遍历。
摘要由CSDN通过智能技术生成

迭代器

Iterator是一种接口,任何数据结构只要部署了Iterator接口,就可以完成遍历操作。
是对象的一种属性:Symbol.iterator,这个属性是个函数。Symbol(Symbol.iterator)
在这里插入图片描述

        const arr=[1,2,3,4];
        let iterator=arr[Symbol.iterator]();//arr[Symbol.iterator]表示调用arr对象的属性//Symbol.iterator,其是个函数,所以括号表示调用,函数调用返回一个对象。
        console.log(iterator.next());

手动实现迭代器:

        function myIterator(arr){
            let index=0;
            return {next(){
                if(index<arr.length){
                    return {value:arr[index++],done:false}
                }
                else{
                    return {value:undefined,done:true}
                }
            }
        }
    }
        arr=[1,2,3,4];
        let iterator=myIterator(arr);
        console.log(iterator.next());

array、string等都部署了迭代器接口,但是对象没有,所以要自定义迭代器接口:

        //自定义迭代器接口让对象可以实现for...of...循环
        var obj={
            a:1,
            b:2,
            c:3,
            [Symbol.iterator](){
                let index=0;
                //因为obj没有length属性,所以用Map映射obj(因为Map有size方法)
                let m=new Map([['a',1],['b',2],['c',3]]);//初始化时传一个数组进去,数组里是键值对

                return {next(){
                let mEntriesArray=[...m.entries()];
                if(index<m.size){
                    return {value:mEntriesArray[index++],done:false}
                }
                else{
                    return {value:undefined,done:true}
                }
            }
        }
    }       
}
var iter=obj[Symbol.iterator]();
console.log(iter.next());
//此时obj也可用for...of迭代了
for(let i of obj){
    console.log(i);
}

迭代和遍历的区别?
迭代:从目标源依次逐个抽取的方式来提取数据,目标源一定是有序的(有索引)并且连续的。如Array、String、Map、Set、arguments、NodeList都可以用for…of…迭代。对象里的数据就不是有序的。

生成器

什么是生成器?生成器是一个带星号的函数(function*),而且可以暂停执行和恢复执行(函数里面的代码不是一次执行完的)。
生成器具体使用方式:

  • 在生成器函数内部执行一段代码,如果遇到 yield 关键字,那么 JavaScript引擎将返回yield关键字后面的内容给外部(父协程),并暂停该函数的执行。
  • 外部函数可以通过 next 方法恢复函数(gen协程)的执行

js引擎V8如何实现一个函数的暂停和恢复执行
需要先来了解一下协程:协程是一种比线程更加轻量级的存在。你可以把协程看成是跑在线程上的任务,一个线程上可以存在多个协程,但是在线程上同时只能执行一个协程,比如当前执行的是 A 协程,要启动 B 协程,那么 A 协程就需要将主线程的控制权交给 B 协程,这就体现在 A 协程暂停执行,B 协程恢复执行;同样,也可以从 B 协程中启动 A 协程。通常,如果从 A 协程启动 B 协程,我们就把 A 协程称为 B 协程的父协程。协程不像线程一样被操作系统内核管理,而是由程序控制,所以协程切换性能更高,没那么消耗资源(线程切换需要消耗CPU)。生成器就是协程的一种实现方式。
协程的四点规则:通过调用生成器函数 genDemo 来创建一个协程 gen,创建之后,gen 协程并没有立即执行;要让 gen 协程执行,需要通过调用 gen.next;当协程正在执行的时候,可以通过 yield 关键字来暂停 gen 协程的执行,并返回主要信息给父协程;如果协程在执行期间,遇到了 return 关键字,那么 JavaScript 引擎会结束当前协程,并将 return 后面的内容返回给父协程。

我们把执行生成器的代码封装成一个函数,并把这个执行生成器代码的函数称为执行器。

生成器返回一个迭代器对象。
迭代器可以通过生成器的方式来生成:

        function* test(){
             console.log(1);
            yield 5;
console.log(2);//在调用第二个next()之前不打印
            let value=yield 2;
console.log(value);
            yield 3;
            yield 4;
        }
        var iter=test();
        console.log(iter.next(‘one’));//调用next()方法才会执行test函数。执行一次yield一下,下面代码中止
         console.log(iter.next(‘two’));
         console.log(iter.next());
         console.log(iter.next());
        //for(let i of iter){
        //    console.log(i);
        //}
//用生成器手动实现迭代器接口
        var obj={
            a:1,
            b:2,
            c:3,
            [Symbol.iterator]:function*(){
                let index=0;
                //因为obj没有length属性,所以用Map映射obj(因为Map有size方法)
                let m=new Map([['a',1],['b',2],['c',3]]);//初始化时传一个数组进去,数组里是键值对
                let mEntriesArray=[...m.entries()];
                while(index<mEntries.length){
                    yield mEntriesArray[index++];
                }        
    }       
}
for(let i of obj){
    console.log(i);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值