Es6 Generator函数详细解析


Posted in Javascript onFebruary 24, 2018

ECMAScript 6 (简称 ES6 )作为下一代 JavaScript 语言,将 JavaScript 异步编程带入了一个全新的阶段。

Generator函数跟普通函数的写法有非常大的区别:

一是,function关键字与函数名之间有一个星号;

二是,函数体内部使用yield语句,定义不同的内部状态(yield在英语里的意思就是“产出”)。

本文重点给大家介绍Es6 Generator函数,具体内容如下所示:

/*    一、generator函数的定义

    1.Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
    2.形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态
   */
  //定义一个generator函数 其内部有3种状态
  var helloGenerator = function *() {
    var next1 = yield 'hello';
    yield 'world' + next1;
    return 'ending';
  }
  //调用generator 函数和普通函数一样,直接加上双括号 () 但是跟普通函数的区别是generator不会立即执行, 返回的也不是函数的结果,而是内部的一个指针。
  var newGenerator = helloGenerator();
  //generator 函数是分段执行的 会从头部直到遇到下一个yield 表达式的时候停止下来。
  console.log(newGenerator.next('hahh')); //Object {value: "hello", done: false}
  console.log(newGenerator.next()); // {value: "worldhahh", done: false}
  console.log(newGenerator.next()); //{value: "ending", done: true}  done true| false true代表的意思内部yield 表达式已经执行完毕 false则相反
  console.log(newGenerator.next()); //{value: "undefined", done: true}
  /*
    总结一下,调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
   */
  /*
    二、yield 表达式
    1.由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
    遍历器对象的next方法的运行逻辑如下。
    (1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
    (2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
    (3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
    (4)如果该函数没有return语句,则返回的对象的value属性值为undefined。
    2.yield 表达式和 return 语句的区别: return 不具有记忆功能, yield 具有记忆功能,下次调用next()方法的时候会接着往下执行。
    一个函数里面只能执行一个return 语句 可以执行多个yield 表达式。 yield 函数只能用在generator 函数里面不能用在其他函数里面,不然会报错。
   */
  /*
    三、与 Iterator 接口的关系
    任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。由于 Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator属性,从而使得该对象具有 Iterator 接口。
   */
  var myIterable = {};
  myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
  };
  console.log([...myIterable]) // [1, 2, 3]
  /*
    四、next 方法的参数
    yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
    意义:可以在 Generator 函数运行的不同阶段,从外部向内部注入不同的值,从而调整函数行为。
   */
  function* foo(x) {
    var y = 2 * (yield (x + 1));
    var z = yield (y / 3);
    return (x + y + z);
  }
  var a = foo(5);
  a.next() // Object{value:6, done:false}
  a.next() // Object{value:NaN, done:false}
  a.next() // Object{value:NaN, done:true}
  var b = foo(5);
  b.next() // { value:6, done:false }
  b.next(12) // { value:8, done:false }
  b.next(13) // { value:42, done:true }
  /*
    五、for...of 循环
    for...of循环可以自动遍历 Generator 函数时生成的Iterator对象,且此时不再需要调用next方法。(有点类似于 ... 对象的扩展运算符)
   */
  function* foo() {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
    yield 5;
    return 6;
  }
  for (let v of foo()) {
    console.log(v);
  }
  // 1 2 3 4 5
  //上面代码使用for...of循环,依次显示 5 个yield表达式的值。这里需要注意,一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,所以上面代码的return语句返回的6,不包括在for...of循环之中。
  //除了for...of循环以外,扩展运算符(...)、解构赋值和Array.from方法内部调用的,都是遍历器接口。这意味着,它们都可以将 Generator 函数返回的 Iterator 对象,作为参数。
  function* numbers () {
    yield 1
    yield 2
    return 3
    yield 4
  }
  // 扩展运算符
  [...numbers()] // [1, 2]
  // Array.from 方法
  Array.from(numbers()) // [1, 2]
  // 解构赋值
  let [x, y] = numbers();
  x // 1
  y // 2
  // for...of 循环
  for (let n of numbers()) {
    console.log(n)
  }
  // 1
  // 2
  /*
  六、Generator.prototype.throw()
   */
  function *testError(){
    try{
      yield ;
    }catch (e){
      console.log(e)
    }
  }
  var testE = testError();
  testE.throw(new Error('会出错吗?'));// 会出错吗? 这个错误是由generator 函数的内部捕获的。
  /*
    七、Generator.prototype.return()
    Generator 函数返回的遍历器对象,还有一个return方法,可以返回给定的值,并且终结遍历 Generator 函数。
   */
  function* gen() {
    yield 1;
    yield 2;
    yield 3;
  }
  var g = gen();
  g.next()    // { value: 1, done: false }
  g.return('foo') // { value: "foo", done: true }
  g.next()    // { value: undefined, done: true }

总结

以上所述是小编给大家介绍的Es6 Generator函数详细解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
使用IE的地址栏来辅助调试Web页脚本
Mar 08 Javascript
HTML Color Picker(js拾色器效果)
Aug 27 Javascript
用jquery修复在iframe下的页面锚点失效问题
Aug 22 Javascript
jquery ztree实现模糊搜索功能
Feb 25 Javascript
AngularJS 使用ng-repeat报错 [ngRepeat:dupes]
Jan 19 Javascript
JS简单实现数组去重的方法示例
Mar 27 Javascript
AngularJS实现的获取焦点及失去焦点时的表单验证功能示例
Oct 25 Javascript
vue项目如何刷新当前页面的方法
May 18 Javascript
微信小程序实现消息框弹出动画
Apr 18 Javascript
js实现一个简易计算器
Mar 30 Javascript
react实现移动端下拉菜单的示例代码
Jan 16 Javascript
vue中封装axios并实现api接口的统一管理
Dec 25 Vue.js
JavaScript中利用Array filter() 方法压缩稀疏数组
Feb 24 #Javascript
解决VUE框架 导致绑定事件的阻止冒泡失效问题
Feb 24 #Javascript
JS抛物线动画实例制作
Feb 24 #Javascript
浅谈VUE监听窗口变化事件的问题
Feb 24 #Javascript
使用watch监听路由变化和watch监听对象的实例
Feb 24 #Javascript
vue watch监听对象及对应值的变化详解
Feb 24 #Javascript
解决Vue不能检测数组或对象变动的问题
Feb 24 #Javascript
You might like
多数据表共用一个页的新闻发布
2006/10/09 PHP
php ftp文件上传函数(基础版)
2010/06/03 PHP
浅析PKI加密解密 OpenSSL
2013/07/01 PHP
PHP可变变量学习小结
2015/11/29 PHP
thinkPHP订单数字提醒功能的实现方法
2016/12/01 PHP
JavaScript高级程序设计 读书笔记之八 Function类及闭包
2012/02/27 Javascript
2012年开发人员的16款新鲜的jquery插件体验分享
2012/12/28 Javascript
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
2015/01/01 NodeJs
javascript针对不确定函数的执行方法
2015/12/16 Javascript
angularjs表格分页功能详解
2016/01/21 Javascript
BootStrap智能表单实战系列(九)表单图片上传的支持
2016/06/13 Javascript
javascript 数据存储的常用函数总结
2017/06/01 Javascript
vue toggle做一个点击切换class(实例讲解)
2018/03/13 Javascript
原生JS与JQ获取元素的区别详解
2020/02/13 Javascript
基于javascript实现日历功能原理及代码实例
2020/05/07 Javascript
解决vue2中使用elementUi打包报错的问题
2020/09/22 Javascript
绘制微信小程序验证码功能的实例代码
2021/01/05 Javascript
[59:35]DOTA2-DPC中国联赛定级赛 Aster vs DLG BO3第一场 1月8日
2021/03/11 DOTA
Python获取apk文件URL地址实例
2013/11/01 Python
以windows service方式运行Python程序的方法
2015/06/03 Python
简单了解python反射机制的一些知识
2019/07/13 Python
Django获取应用下的所有models的例子
2019/08/30 Python
Python超越函数积分运算以及绘图实现代码
2019/11/20 Python
基于Tensorflow的MNIST手写数字识别分类
2020/06/17 Python
Python爬虫与反爬虫大战
2020/07/30 Python
英国、欧洲和全球租车服务:Avis英国
2016/08/29 全球购物
New Balance加拿大官方网站:运动鞋和健身服装
2018/11/19 全球购物
班级体育活动总结
2014/07/05 职场文书
关于国庆节的演讲稿
2014/09/05 职场文书
法定代表人授权委托书
2014/09/19 职场文书
学校政风行风评议工作总结
2014/10/21 职场文书
大学生村官个人总结
2015/02/15 职场文书
2015大学自主招生自荐信范文
2015/03/04 职场文书
Go语言中的UTF-8实现
2021/04/26 Golang
Redis缓存-序列化对象存储乱码问题的解决
2021/06/21 Redis
大型强子对撞机再次重启探索“第五种自然力”
2022/04/29 数码科技