Generator函数介绍
Generator函数
基本概念
英文意思为 “生成器”。
generator函数是es6提供的一种异步编程解决方案,语法行为与传统函数完全不同。从状态上,首先我们把他理解成一种状态机,封装了多个内部状态。另外执行generator函数胡返回一个遍历对象,就是说,generator函数还是一个遍历器对象生成函数,可以一次遍历函数中的每一个状态。
generator函数的两个特征
- function命令与函数名之间有一个星号;
- 函数体内部使用yield语句定义不同的内部状态(yield为“产出”的意思)。
调用generator函数后,该函数并不执行,返回的也不是函数的运行结果,而是一个指向内部状态的指针对象,也就相当于遍历器对象。下一步必须调用遍历器对象的next方法,使得指针移向下一个状态。就是说每次调用next方法,内部指针就从函数头部或上次停留的地方开始执行,直到遇到吓一跳yield语句或是return语句时停止。yield语句是generator函数的暂停执行,next是恢复执行。
yield语句
是generator函数的暂停标志。
- next方法的运行逻辑:
- 遇到yield语句就暂停执行后面的操作,并将紧跟在yield后面表达式的值作为返回的对象的value属性值。
- 下次调用next方法时再继续往下执行,直到遇到下一个yield语句;
- 如果没有遇到新的yield语句,就一直运行到函数结束,直到遇到return语句为止,并将return语句后面的表达式的值作为返回对象的value属性值;
- 如果该函数没有return语句,则返回对象的value属性值为undefined
注意: yield语句为javascript提供了手动的 “惰性求值”。
yield语句与return语句有相似之处也有区别,相似之处在于都返回紧跟在后面的值,区别在于return语句不具备记忆功能。
var arr = [1, [[2,3],4],[5,6]];
var flat = function* (a){
a.forEach(function(item){
if(typeof item !== 'number'){
yield* flat(item);
}else{
yield item;
}
});
}
for(var f of flat(arr)){
console.log(f);
}
这个例子将会报错,因为forEach方法的参数是个普通的函数,但是里面使用了yield语句,普通函数里面是不允许是使用yield语句的。
那么我们来修改一下
var arr = [1, [[2,3],4],[5,6]];
var flat = function* (a){
var length = a.length;
for(var i =0; i < length; i++){
var item = a[i];
if(typeof item !== 'number'){
yield* flat(item);
}else{
yield item;
}
}
};
for(var f of flat(arr)){
console.log(f);
}// 1, 2, 3, 4, 5, 6
- 与Iterator接口的关系
任意一个对象的Symbol.iterator方法等于该对象的遍历器对象生成函数,调用该函数会返回该对象的一个遍历器对象。
遍历器对象本身也有Symbol.iterator方法,执行后返回自身。
function* gen(){
//some code
}
var g = gen();
console.log(g[Symbol.iterator]() === g);
gen是一个generator函数,调用它会生成一个遍历器对象g,他的Symbol.iterator属性也是一个遍历器对象生成函数,执行后返回自己。
yield* 语句
如果在generator函数内部调用另一个generator函数,默认情况下是没有效果的。
yield*语句,专门用来在一个generator函数里面执行另一个generator函数。
function* foo(){
yield 'a';
yield 'b';
}
function* bar(){
yield 'x';
yield* foo();
yield 'y';
} for(let v of bar()){
console.log(v);
}
上面将会返回x, a, b, y。如果直接调用foo函数的话,将不会有什么效果。
如果yield命令后面没有星号,将返回一个遍历器对象,加上星号后将会返回遍历对象的具体值。yield* 语句相当于在generator函数内部部署了一个for...of循环。
function* concat(iter1, iter2){
yield* iter1;
yield* iter2;
}
//等同于
function* concat(iter1, iter2){
for(var value of iter1){
yield value;
}
for(var value of iter2){
yield value;
}
}
还应注意的是,如果在遍历数组时,用yield命令将会返回全部都的数组成员,yield* 则返回单个字符:即数组的第一个成员。
如果generator函数有return语句,那么将会返回相应的数据,如果return()不带任何参数,则相应位置返回的值为undefined。
yield* 命令可以很方便的取出嵌套数组的所有成员。
function* iterTree(tree){
if(Array.isArray(tree)){
for(let i = 0; i < tree.length; i++){
yield* iterTree(tree[i]);
}
}else{
yield tree;
}
} const tree = ['a', ['b', 'c'], ['d', 'e']]; for(let x of iterTree(tree)){
console.log(x);
}// a b c d e
Generator函数的this
Generator函数总是返回一个遍历器,这个遍历器是generator函数的实例。
function* g(){
this.a = 11;
}
let obj = g();
console.log(obj.a);//undefined
上面的代码中,函数g总是返回遍历器对象,而不是this对象,这时使用new命令就不能生成对应函数的实例,因为函数返回的是一个内部指针。如果想让generator函数能有正常的构造函数,就可以采用:先生成一个空对象,使用bind方法绑定generator函数内部的指针,这样,构造函数调用之后这个空对象就是generator函数的实例对象了。
function* F(){
yield this.x = 2;
yield this.y = 3;
}
var obj = {};
var f = F.bind(obj)();
f.next();
f.next();
f.next();
console.log(obj);//Object{value: 2, done: false}
通过generator函数部署Ajax操作
function* main(){
var result = yield request("http://some.url");
var resp = JSON.parse(result);
console.log(resp.value);
}
function request(url){
makeAjaxCall(url, function(response){
it.next(response);
});
}
var it = main();
it.next();
上面的main函数就是通过AJAX获取到的数据,makeAjaxCall函数的next方法中必须加上response参数,因为yield语句构成的表达式本身是没有值的,总是等于undefined。
Generator函数介绍的更多相关文章
- ES6 - Note7:Generator函数
Generator函数 1.Generator函数是ES6增加的异步编程解决方案之一,与普通的函数行为完全不同,类似于一个状态机,内部封装了多个状态. 在函数定义的形式上,跟普通函数差不多,有两处不同 ...
- 转: ES6异步编程:Generator 函数的含义与用法
转: ES6异步编程:Generator 函数的含义与用法 异步编程对 JavaScript 语言太重要.JavaScript 只有一根线程,如果没有异步编程,根本没法用,非卡死不可. 以前,异步编程 ...
- Generator函数语法解析
转载请注明出处: Generator函数语法解析 Generator函数是ES6提供的一种异步编程解决方案,语法与传统函数完全不同.以下会介绍一下Generator函数. 写下这篇文章的目的其实很简单 ...
- Generator函数异步应用
转载请注明出处: Generator函数异步应用 上一篇文章详细的介绍了Generator函数的语法,这篇文章来说一下如何使用Generator函数来实现异步编程. 或许用Generator函数来实现 ...
- ES6的generator函数
generator是什么? generator是ES6提供的一种异步编程解决方案,在语法上,可以把它理解为一个状态机,内部封装了多种状态.执行generator,会生成返回一个遍历器对象.返回的遍历器 ...
- ECMAScript 6 入门 ----Generator 函数
本文转自:阮一峰老师的ECMAScript 6 入门,有时间可以看下评论! Generator 函数 简介 基本概念 Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不 ...
- 一次搞懂 Generator 函数
1.什么是 Generator 函数 在Javascript中,一个函数一旦开始执行,就会运行到最后或遇到return时结束,运行期间不会有其它代码能够打断它,也不能从外部再传入值到函数体内 而Gen ...
- ES 6 proimse &&iterator &&Generator函数 &&async
1.proimse 异步调用function getData(){ let promise =new Promise((resolve,reject)); let xmlHttp =new XMLHt ...
- JavaScript中的Generator函数
1. 简介 Generator函数时ES6提供的一种异步编程解决方案.Generator语法行为和普通函数完全不同,我们可以把Generator理解为一个包含了多个内部状态的状态机. 执行Genera ...
随机推荐
- Nuxt使用scss
Nuxt中使用scss也很简单,分简单的几步就OK 一.安装scss依赖 用IDE打开项目,在Terminal里通过 npm i node-sass sass-loader scss-loader - ...
- 转载:Linux下查看/修改系统时区、时间
一.查看和修改Linux的时区 1. 查看当前时区 命令 : "date -R" 2. 修改设置Linux服务器时区 方法 A 命令 : "tzselect" ...
- 0404-服务注册与发现-客户端负载均衡-两种自定义方式-Ribbon通过代码自定义配置、使用配置文件自定义Ribbon Client
一.官方文档解读 官方地址:https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_cust ...
- boost之内存池
讲到内存池我们会想到对对象进行动态分配的过程new包含三个过程 1.使用operator new分配内存 2.使用placement new 初始化 3.返回内存地址. 分配内存可以分解成分配内存和获 ...
- 47求1+2+3+...+n
题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 用递归 public class Soluti ...
- bug营销手段
肯德基搞事了. 几乎是一夜之间,肯德基App就杀进了iOS热门App排行榜的前50名. 一夜之间排名猛增,一定是事出有因的.那这次的原因是什么? bug. 肯德基App出现了一个大bug,用户将账号生 ...
- 026_默认的MapReduce Driver(最小驱动问题)
1. 最小配置的MapReduce Driver 读取输入文件中的内容,输出到指定目录的输出文件中,此时文件中的内容为: Key---输入文件每行内容的起始位置. Value---输入文件每行的原始内 ...
- mongodb简介和特性
1.mongodb是基于文档的(BSON,类似json的键值对来存储),不是基于表格,易于水平扩展,将内部相关的数据放在一起能提高数据库的操作性能.如果你想新建一个新的文档类型,不用事先告诉数据库关于 ...
- 大数据架构之:Kafka
Kafka 是一个高吞吐.分布式.基于发布订阅的消息系统,利用Kafka技术可在廉价PC Server上搭建起大规模消息系统.Kafka具有消息持久化.高吞吐.分布式.多客户端支持.实时等特性,适用于 ...
- 关于在windows命令提示符cmd下运行Java程序的问题
1. win+R出现cmd运行窗口,输入Java源码文件名运行时,错误: 找不到或无法加载主类... 问题背景:我已经配置好了Java环境(安装路径PATH,JAVA_HOME已装好,cmd运行jav ...