一种特殊的生成器函数-Generator函数

coderhf 2020-04-28 原文

本节的内容,是建立在iterator遍历器知识的基础上。所以希望还没有看上一节的内容的话,最好还是看一看,当然你如果熟悉iterator就没有那个必要了.

既然你都看到这里来了,就咱们就接着往下讲…

声明Generator函数

我们要学习的这个新函数叫做:Generator函数,又称生成器函数,是ES6的一个重要的新特性。

我们来看看这个函数张什么模样:

 //声明一个Hello的Generator函数
    function* Hello(name) {
        yield `hello ${name}`;
        yield `how are you`;
        yield `bye`;
    }

 

上面这个就是Generator函数,乍一看,是不是跟普通的函数没什么两样?确实很像,但是我们要知道它有两个重要的区别:

  1. 普通函数用function来声明,Generator函数用function*声明。

  2. Generator函数内部有新的关键字:yield,普通函数没有。

PS:函数体内用到了ES6的新特性:字符串模板。第六节的内容,点击可以查看。

了解了Generator函数的声明方式,我们又多了两个疑问:

  1. Generator函数运行起来会发生什么?

  2. ****关键字yield语句的作用是什么?

调用Generator函数

带着这两个疑问我们往下看,我们试着就调用一下这个名字叫Hello的Generator函数,看看会发生什么:

 //声明一个Hello的Generator函数
    function* Hello(name) {
        yield `hello ${name}`;
        yield `how are you`;
        yield `bye`;
    }

    //调用Hello函数
    let ite = Hello('前端君');
    //结果:[object Generator]

    ite.next();
    //{value: "hello 前端君", done: false}

    ite.next();
    //{value: "how are you", done: false}

    ite.next();
    //{value: "bye", done: false}

    ite.next();
    //{value: undefined, done: true}

 

看到这里,估计你也看到了一个熟悉的面孔:next()方法。(上一节iterator遍历器的内容)。

我们一起看看整个过程发生了什么:

一开始,我们调用Hello(“前端君”),函数执行后,返回了一个:[object Genrator]生成器对象,我们把它赋值到变量ite中,仅此而已,并没有做太多的事情。

接着,第1次调用生成器对象ite的next( )方法,返回了一个对象:

{value: "hello 前端君", done: false}

 

第2次调用生成器对象ite的next( )方法,同样得到了一个对象:

{value: "how are you", done: false}

 

第3次调用生成器对象ite的next( )方法,又得到了一个对象:

{value: "bye", done: false}

 

直到,第4次调用生成器对象ite的next( )方法,返回的对象:

{value: undefined, done: true}

 

看到这里有没有发现,这里生成器的next( )方法的和遍历器iterator的next( )方法的返回结果是不是一样?

没错,你可以把Generator函数被调用后得到的生成器理解成一个遍历器iterator,用于遍历函数内部的状态。(所以要求大家先学习第十三节iterator遍历器的知识)

Generator函数的行为

通过上面的案例,我们知道了:Generator函数被调用后并不会一直执行到最后,它**是先回返回一个生成器对象,然后hold住不动****,等到生成器对象的next( )方法被调用后,函数才会继续执行,直到遇到关键字yield后,又会停止执行,**并返回一个Object对象,然后继续等待,直到next( )再一次被调用的时候,才会继续接着往下执行,直到done的值为true。

yield语句的作用

而yield在这里起到了十分重要的作用,就相当于暂停执行并且返回信息。有点像传统函数的return的作用,但不同的是普通函数只能return一次,但是Generator函数可以有很多个yield。而return代表的是终止执行,yield代表的是暂停执行,后续通过调用生成器的next( )方法,可以恢复执行

next( )方法接收参数

此外,next( )方法还可以接受一个参数,它的参数会作为上一个yield的返回值,我们来看一下:

//声明一个Hello的Generator函数
    function* Hello() {
        let res = yield `hello`;
        yield res;
    }
    
    let iterator = Hello();
    //结果:一个生成器对象

    iterator.next();
    //结果:{value: "hello", done: false}

    iterator.next("前端君");
    //结果:{value: "前端君", done: false}

 

注意函数体内的第一个yield关键字,我们把它的返回值赋值给了一个变量res。

再看2次next方法的调用:

第1次调用next( )方法,返回的对象属性value值为“hello”,属性done值为:fasle,并暂停执行。

第2次next( )方法,传入参数:字符串“前端君”。此时,第二个yield关键字紧跟着的是变量res,而变量res的值正是上一个关键字yield的返回值。也就是说这个值正是我们传入的参数:“前端君”。因为:next( )的参数会作为上一个yield的返回值。

慢慢体会一下,理清逻辑,稍微有点绕。

关键字yield*

在一个Generator函数里面,如果我们想调用另一个Generator函数,就需要用到的关键字是:yield*。

我们来看看怎么玩,代码有点长,但是很好理解:

 //声明Generator函数:gen1   
    function* gen1() {
        yield "gen1 start";
        yield "gen1 end";
    }

    //声明Generator函数:gen2
    function* gen2() {
        yield "gen2 start";
        yield "gen2 end";
    }

    //声明Generator函数:start
    function* start() {
        yield "start";
        yield* gen1();
        yield* gen2();
        yield "end";
    }

    //调用start函数
    var ite = start();
    //创建一个生成器
    
    ite.next();
    //{value: "start", done: false}

    ite.next();
    //{value: "gen1 start", done: false}

    ite.next();
    //{value: "gen1 end", done: false}

    ite.next();
    //{value: "gen2 start", done: false}

    ite.next();
    //{value: "gen2 end", done: false}

    ite.next();
    //{value: "end", done: false}
    

 

我们主要看start( )这个Generator函数,其中有两句代码:

   yield* gen1();
    yield* gen2();

 

这里使用了关键字yield*来实现调用另外两个Generator函数。从后面的多个next( )方法得到的结果看,我们可以知道:

** 如果一个Generator函数A执行过程中,进入(调用)了另一个Generator函数B,那么会一直等到Generator函数B全部执行完毕后,才会返回Generator函数A继续执行。**

Generator函数的用途

以上就是对Generator函数的讲解介绍,它是ES6的一个很重要的新特性。它可以控制函数的内部状态,依次遍历每个状态;可以根据需要,轻松地让函数暂停执行或者继续执行。

根据这个特点,我们可以利用Generator函数来实现异步操作的效果。

原理是:利用Generator函数暂停执行的作用,可以将异步操作的语句写到yield后面,通过执行next方法进行回调。

本节小结

总结:Generator函数是一种特殊的函数,可以使用关键字yield和next( )实现暂停和继续执行,而关键字yield*专门用于调用Generator函数,看似简单的特性,在实际开发中却有极大的用处。
更多前端学习内容文章干货请关注我的专栏(不断更新)

阿里名厂标准web前端高级工程师教程目录大全,从基础到进阶,看完保证您的薪资上升一个台阶

在这里我给大家准备了很多的学习资料
其实你与阿里工程师的差距只差这些东西

版权声明:本文为coderhf原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/coderhf/p/12793721.html

一种特殊的生成器函数-Generator函数的更多相关文章

随机推荐

  1. Ubuntu查看和设置Root账户 – 小子有出息

    Ubuntu查看和设置Root账户 前言:   要在Linux中运行管理任务,必须要具有root(也称为超级用 […]...

  2. jquery 跨域获取网页数据

    <script language=”javascript” src=” […]...

  3. android中使用spinner组件

    spinner组件类似于html中的select标签,实现下拉选择框的功能。 添加一个Activity,界面上 […]...

  4. Hibernate常用查询语句 Hibernate常用查询语句

    Hib的检索方式1\’导航对象图检索方式。通过已经加载的对象,调用.iterator()方法可以得 […]...

  5. java之方法覆盖的坑

      昨天写了个小例子,覆盖hashCode、equals进行集合set的一些特性测试,代码如下:   clas […]...

  6. 【转载】云服务器(linux)切换到root 用户

    【原文地址】:https://blog.csdn.net/weixin_38801572/article/de […]...

  7. 单片机结构和原理

    89C51单片机结构框图 1、一个8位 的微处理器CPU。 2、片内数据存储器(RAM128B/256B):用 […]...

  8. Reversing Linked List

    Reversing Linked List Given a constant K and a singly l […]...

展开目录

目录导航