ECMAScript6 入门 Generator

----------------------------------------------------------------------------------------------------------------------------

基本概念
Generator 函数是一个状态机,封装了多个内部状态,执行 Generator 函数会返回一个遍历器对象
Generator 函数除了状态机,还是一个遍历器对象生成函数,
返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态

function* helloWorldGenerator() {
  yield ‘hello‘;
  yield ‘world‘;
  return ‘ending‘;
}

var hw = helloWorldGenerator();
该函数存在三个状态了

----------------------------------------------------------------------------------------------------------------------------

调用 Generator 函数后,该函数并不执行
返回的也不是函数运行结果,而是一个指向内部状态的指针对象(遍历器对象)

下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态
返回的对象是yield表达式的值以及遍历是否完成
(遇到下一个yield或者return为止)
hw.next()
// { value: ‘hello‘, done: false }

hw.next()
// { value: ‘world‘, done: false }

hw.next()
// { value: ‘ending‘, done: true }

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

----------------------------------------------------------------------------------------------------------------------------

yield 表达式
遍历器对象的next方法的运行逻辑如下
(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,
并将return语句后面的表达式的值,作为返回的对象的value属性值。
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。
注意:yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行(如果没有执行到这一步,就永远都不会执行该表达式)
(因此相等于手动提供了一个“惰性求值”的语法功能)
(5)yield不能进行嵌套操作,并且yield必须在定义的function*()函数里面,在数组等其他的回调函数是不起作用
//(6) yiled 后面使用的返回必须是返回了一个Promise对象

重点:bluebirdjs 类库会将普通函数转化成返回Promise对象的函数

----------------------------------------------------------------------------------------------------------------------------
next() 方法的参数
1:该参数会被当成上一个yield表达式的返回值
----------------------------------------------------------------------------------------------------------------------------

for...of 循环
for...of循环可以自动遍历 Generator 函数时生成的Iterator对象,且此时不再需要调用next方法
1:一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,就是不包含最后的那个return

----------------------------------------------------------------------------------------------------------------------------

Generator.prototype.throw()
Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获

----------------------------------------------------------------------------------------------------------------------------

Generator.prototype.return()
Generator 函数返回的遍历器对象,还有一个return方法,可以返回给定的值,并且终结遍历 Generator 函数
注释:return与next的简单区别
1:console.log(g.return(‘foo‘)); // { value: "foo", done: true } 终结了所以是true,并且返回了指定的值
2:return没有参数的时候,返回{ value: undefined, done: true }
3:next没有参数的时候返回本次yield语句的返回值
4:return有参数的时候,覆盖本次yield语句的返回值,也就是说,返回{ value: 参数, done: true };
next有参数的时候,覆盖上次yield语句的返回值

----------------------------------------------------------------------------------------------------------------------------

next()、throw()、return() 的共同点
next()、throw()、return()这三个方法本质上是同一件事,可以放在一起理解。它们的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换yield表达式

----------------------------------------------------------------------------------------------------------------------------

yield* 表达式
如果在 Generator 函数内部,调用另一个 Generator 函数,默认情况下是没有效果的
单纯的使用另一个Generator无效
yield* fn() 这样才会起效果

----------------------------------------------------------------------------------------------------------------------------

作为对象属性的 Generator 函数

----------------------------------------------------------------------------------------------------------------------------

Generator 函数的this

----------------------------------------------------------------------------------------------------------------------------

Generator 与状态机
1:常用的状态机写法
var ticking = true;
var clock = function() {
  if (ticking)
    console.log(‘Tick!‘);
  else
    console.log(‘Tock!‘);
  ticking = !ticking;
}
上面代码的clock函数一共有两种状态(Tick和Tock),每运行一次,就改变一次状态:

2:Generator的写法
var clock = function*() {
  while (true) {
    console.log(‘Tick!‘);
    yield;
    console.log(‘Tock!‘);
    yield;
  }
};

----------------------------------------------------------------------------------------------------------------------------
Generator 函数的异步应用

已知的异步编程
{
    回调函数
    事件监听
    发布/订阅
    Promise对象
}

回调函数写法
fs.readFile(‘/etc/passwd‘, ‘utf-8‘, function (err, data) {
  if (err) throw err;
  console.log(data);
});

Promise写法
var readFile = require(‘fs-readfile-promise‘);

readFile(fileA)
.then(function (data) {
  console.log(data.toString());
})
.then(function () {
  return readFile(fileB);
})
.then(function (data) {
  console.log(data.toString());
})
.catch(function (err) {
  console.log(err);
});

Generator写法
function* gen(x) {
  var y = yield x + 2;
  return y;
}

var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }

数据交换与错误解决
{
    next返回值的value属性,是Generator函数向外输出,next函数还可以接受参数向函数体输入数据
    Generator函数体内部还可以部署错误处理代码,捕获函数体外抛出的错误

}

参数的求值策略
{
    传值调用:在进入函数体之前进行调用
    传名调用:将表达式传入函数体,在执行的时候才调用
}

Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数

Generator函数的自动执行方法
{

}

原文地址:https://www.cnblogs.com/panrui1994/p/11597685.html

时间: 2024-10-28 20:00:23

ECMAScript6 入门 Generator的相关文章

ECMAScript6 入门 函数的扩展

为函数参数设定默认值 function log(x, y = 'World') { console.log(x, y); } log('Hello') // Hello World log('Hello', 'China') // Hello China log('Hello', '') // Hello 注意:参数变量是默认声明的,所以不能用let或const再次声明 使用参数默认值时,函数不能有同名参数 // 不报错 function foo(x, x, y) { // ... } // 报

ECMAScript6入门学习--第一天

ECMAScript与javascript的关系 ECMA是是一个国际标准化的一个组织,规定了浏览器脚本的语言标准,在上个实际,javascript公司Netscape把javascript托付给ECMA,让其为javascript设置标准,经常见到到版本ES5就是在ES6的上一代标准. let   什么是let? 狭义理解let是更完美的var,也就是说 他是用来声明变量,方法与var类似,但是优于var,那它的优点是什么呢,下面将详述 let声明的变量只在该变量的代码块中有效 { var a

ECMAScript6 入门 变量的解析赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring) 这句话的解释:第一步从数组或者对象中提取值,第二步将提取到的值对变量进行赋值 1数组的解析赋值 如果解析不成功,那么对应的变量为undefined,同时如果等号的右侧不是可遍历的数据结构,也会进行报错. 解析允许存在默认值,注意,ES6内部使用严格相等运算符,来判断一个位置是否有值,所以只有当一个数组的成员严格等于undefined时,默认值才会起作用     2对象的解析赋值 对象解析与

ECMAScript6 入门 Module

目的:将大程序拆分成互相依赖的小模块文件.CommonJS 和 AMD 两种,前者用于服务器,后者用于浏览器.他俩都是运行时才确定 :ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量 // CommonJS模块 let { stat, exists, readFile } = require('fs'); // 等同于 let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exis

深入解析js异步编程利器Generator

我们在编写Nodejs程序时,经常会用到回调函数,在一个操作执行完成之后对返回的数据进行处理,我简单的理解它为异步编程. 如果操作很多,那么回调的嵌套就会必不可少,那么如果操作非常多,那么回调的嵌套就会变得让人无法忍受了. 我们知道的Promises就是问了解决这个问题而提出来的.然而,promises并不是一种新的功能,它只是一种新的写法,原来横向发展的回调函数,被排成了队竖向发展. 然而,Generator不同,它是一种新的解决方案. 文章中提到的所有代码都可以在这里找到源码:[查看源码].

javascript基础(第四天)

ECMAScript6预计将在 2015年6月 正式发布 chrome测试语法需要引入Traceur编辑器https://github.com/google/traceur-compiler 了解未来的语法和趋势, 未来1年内估计也用到不, 这里只做基本的了解. let 变量声明 {    let a = 10; //只在代码块内有效,适用于for,if等方法体    var b = 20;}console.log(a); // ReferenceError a is not definedco

高级前端面试题目大全(一)

第 1 题:(滴滴.饿了么)写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么? 1. 更准确 因为带key就不是就地复用了,在sameNode函数 a.key === b.key对比中可以避免就地复用的情况.所以会更加准确. 2. 更快 利用key的唯一性生成map对象来获取对应节点,比遍历方式更快.主要是为了提升diff[同级比较]的效率.自己想一下自己要实现前后列表的diff,如果对列表的每一项增加一个key,即唯一索引,那就可以很清楚的知道两个列表谁少了谁没变

高级前端面试题 js 2

第 1 题:(滴滴.饿了么)写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么? 1. 更准确因为带key就不是就地复用了,在sameNode函数 a.key === b.key对比中可以避免就地复用的情况.所以会更加准确. 2. 更快利用key的唯一性生成map对象来获取对应节点,比遍历方式更快.主要是为了提升diff[同级比较]的效率.自己想一下自己要实现前后列表的diff,如果对列表的每一项增加一个key,即唯一索引,那就可以很清楚的知道两个列表谁少了谁没变.而

【转载】前端学习路径

前端学习路径 什么是前端工程师? 总而言之前端工程师就是运用HTML/CSS/JavaScript等Web技术,在工作中配合设计师实现用户界面,和后端工程师进行数据对接,完成Web应用开发的职位. 开发工具 设计软件 前端工程师最首要的任务就是把设计师的设计图切好并翻译成代码,所以我们要学习一些设计软件的基础操作和切图方法. Photoshop 运用最广泛的设计软件,大部分人都在用它,很有必要学习一下 前端工程师必备的PS技能——切图篇 Sketch 轻量且功能强大,切图迅速高效,为UI设计而生