ES6之Generator函数(4)知识点总结(十一)

原创 2018年04月16日 10:16:20

Generator函数的数据交换和错误处理。

Generator函数可以暂停执行和恢复执行,这是它能封装异步任务的根本原因。除此之外,它还有两个特性,使他可以作为异步编程的完整解决方案:函数体内的数据交换和错误处理机制。next返回值的value属性,是Generator函数向外输出数据,next方法还可以接受参数,向Generator函数体内输入数

function *g(x){
    yield "leo";
  var y=  yield  "lalalal"+x;
    return y;

}
var p = g(1);
console.log(p.next());// { value: "leo", done: false }
console.log(p.next('donna'));//{ value: "lalalal1", done: false }
console.log(p.next("honery"));//{ value: "honery", done: true }
console.log(p.next("honery"));// { value: undefined, done: true }

Generator函数内部还可以部署错误处理代码,捕获函数体外抛出的错误

    try {
        var y = yield x + 2;
    } catch (e){
        console.log(e);
    }
    return y;
}

var g = gen(1);
console.log(g.next());//{ value: 3, done: false }
g.throw('出错了');
console.log(g.next(12));//{ value: undefined, done: true }

上面的代码,在Generator函数体外,使用指针对象的throw方法抛出的错误,可以被函数体内的try…catch代码块捕获。这意味着,出错的代码与处理错误的代码,在时间和空间上的分离。

再看一个例子

function* gen(x){
    try {
        var y = yield x + 2;
    } catch (e){
        console.log(e);
    }
    yield "donna";
    return y;
}

var g = gen(1);
console.log(g.next());//{ value: 3, done: false }
console.log(g.throw('出错了'));//{ value: "donna", done: false }
console.log(g.next(12));//{ value: undefined, done: true }

我们之前说过,go.throw方法被捕获以后,自动执行了一次next方法,但从上面的两个例子中我们可以发现,go.throw方法只会自动执行yield语句,但并不自动执行return语句,这和调用next方法还是有区别的。当然,只要Generator函数内部部署了try…catch代码块,那么遍历器的throw方法抛出的错误,不影响下一次遍历,这也是从上面的代码中可以看到的。


之前忽略了next方法参数的作用,今天给补上

next方法的参数:

yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当做上一个yield表达式的返回值。

注意,由于next方法的参数表示上一个yield表达式的返回值,所以,在第一次调用next方法时,传递的参数是无效的,只有第二次调用next方法,传递的参数才是有效的。从语法上讲,第一个next方法用于启动遍历器对象,所以不用带参数。

看个例子

function *g(x){
    yield 2+x;
  var y=  2*(yield  3+x);
  yield y;
    return y+x;

}
var p = g(1);
console.log(p.next());// { value: 3, done: false }
console.log(p.next(7));// { value: 4, done: false }
console.log(p.next(5));// { value: 10, done: false }
console.log(p.next(5));// { value: 11, done: false }
console.log(p.next(6));// { value: undefined, done: false }
切记:next方法返回的是yield表达式后面的值,next方法传递的参数不是x的值,而是上一个yield表达式的返回值(不是上一个整个表达式的值,知识yield后面的值)。所以上面的代码,第一次调用next方法时,返回的是2+x,x=1,所以就是3,第二次调用next方法,虽然传递了参数,但它代表的上一个yield表达式的值,而我们并没有使用这个值,第三次调用next方法的时候,传递的参数为4,说明上一个yield表达式3+x=5,所以y = 2*5=10,所以这一次yield的值为10,第四次调用next方法,由于y=10,x=1,所以返回的结果就是11.
function *g(x){
    yield 2+x;
  var y=  2*(yield  3+x);
  yield y+1;
    yield y+x;

}
var p = g(1);
console.log(p.next());// { value: 3, done: false }
console.log(p.next(7));// { value: 4, done: false }
console.log(p.next(5));// { value: 11, done: false }
console.log(p.next(5));// { value: 11, done: false }此处y=10,x=1
console.log(p.next(6));// { value: undefined, done: false }
    function *g(x){
        yield 2+x;
        var y=  2*(yield  3+x);
       var z =  yield y+1;
        yield z+x+y;

    }
    var p = g(1);
    console.log(p.next());// { value: 3, done: false }
    console.log(p.next(7));// { value: 4, done: false }
    console.log(p.next(5));// { value: 11, done: false }
    console.log(p.next(5));// { value: 16, done: false }此处z=5,y=10,x=1
    console.log(p.next(6));// { value: undefined, done: false }

还有下面的情况

    function *g(x){
        yield 2+x;
        var y=  2*(yield  3+x);
       var z =  yield 1;
        yield z+x+y;

    }
    var p = g(1);
    console.log(p.next());// { value: 3, done: false }
    console.log(p.next(7));// { value: 4, done: false }
    console.log(p.next(5));// { value: 1, done: false }
    console.log(p.next(5));// { value: 16, done: false }
    console.log(p.next(6));// { value: undefined, done: false }
    function *g(x){
        yield 2+x;
        var y=  2*(yield  3+x);
       var z =  yield 1;
        yield z+x+y;

    }
    var p = g(1);
    console.log(p.next());// { value: 3, done: false }
    console.log(p.next(7));// { value: 4, done: false }
    console.log(p.next());// { value: 1, done: false }
    console.log(p.next(5));// { value: NaN, done: false }
    console.log(p.next(6));// { value: undefined, done: false }

做一个小小的总结:next方法返回一个对象,它的value属性就是当前yield表达式的值(此处暂且不讨论done属性的值),如果next方法在调用的时候传递了参数(不包括第一个调用next方法),那么这个参数就是上一个yield表达式的返回值,也可以说就是当上一个yield表达式整体(或yield整体运算后)赋值给了一个变量,而下一次调用next方法,上一个yield表达式的值就是本次next方法的参数,如果没有传参,则为undefined。(还有就是不要和next参数和Generator参数搞混喽)

这几个对比,每一个改动都很小,把我的疑惑的疑惑解决了,我自己总结了一下,可能有些说法不太科学,仅供参考(当然如果哪里说法不对,也希望您可以提出您的宝贵意见),实践才是检验真理的唯一标准,嗯、还是要多动手才是。


版权声明: https://blog.csdn.net/lhjuejiang/article/details/79955724

ES6学习笔记之Generator 函数的语法

简介基本概念Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。本章详细介绍Generator 函数的语法和 API,它的异步编程应用请看《Generator ...
  • Real_Bird
  • Real_Bird
  • 2017-02-22 16:42:42
  • 854

ECMAScript 6 学习系列课程 (ES6 Generator 函数的使用)

在学习ES6的过程中,个人认为Generator稍微会有些难以理解,其实Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。我们从表面上看,Generator函数是一...
  • jiangbo_phd
  • jiangbo_phd
  • 2016-07-04 16:17:16
  • 2611

ES6入门二(常见的面试点)

项目中对应的代码github的地址:https://github.com/Barretem/ES6_demo_list5、面向对象es5类以及类的继承//父类 function User(name, ...
  • barret007
  • barret007
  • 2018-03-08 23:37:07
  • 67

ES6学习总结

  • 2017年08月14日 10:54
  • 1.59MB
  • 下载

ES6-Generator与异步操作

Generator与异步操作 1.Generator概念 可以把Generator理解成一个状态机(好像React中有很多state),封装了多个内部状态。执行Generator返回的是一个遍历器对...
  • qiqingjin
  • qiqingjin
  • 2016-04-22 16:52:11
  • 2061

JavaScript基于ES6的重点知识点

JavaScript基于ES6的重点知识点 定义变量多用let,少用var 作为全局是平等的。 在函数里也是平等的。 在块中不同。 let 只是在 for 循环中可见,var 却是在整个函数都是可见...
  • dy_qin
  • dy_qin
  • 2017-12-07 17:46:01
  • 95

es6 Generator Thunk函数实现自动执行

function *gen(){ var res = yield 1+2; yield 2+3; yield 3+4; } var genFun = gen(); 执行流程...
  • qq_16515187
  • qq_16515187
  • 2017-10-25 20:04:29
  • 204

es6 Generator函数的语法

es6 中的Generator
  • hzaini89
  • hzaini89
  • 2017-03-23 16:47:58
  • 310

ES6学习——总结

JS从ES3.1到ES5再到ES6,可以说有了本质性的进步,API越来越多,语言特性也越来越丰富,这些都是随着Web的发展而来。以前的JS基本只能用在桌面PC网页端,但现在JS真是无处不在,后端有no...
  • kittyjie
  • kittyjie
  • 2016-02-08 16:30:30
  • 981

ES6(三) Generator (生成器)函数

ES6 Generator (生成器)函数
  • Dason_yu
  • Dason_yu
  • 2017-03-16 14:15:05
  • 899
收藏助手
不良信息举报
您举报文章:ES6之Generator函数(4)知识点总结(十一)
举报原因:
原因补充:

(最多只允许输入30个字)