Generator函数(一)
Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。对于这个函数有多种理解。从语法上来理解,可以将它理解成一个状态机,封装了多个内部状态。内部的不同状态是通过yield语句来定义不同的内部状态,return语句也可以看成一个状态。
基本概念
执行Generator函数会返回一个遍历器对象。
//ES6没有规定function关键字与函数名之间的星号写在哪个位置
function* helloWorldGenerator(){
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
这个函数的调用方式和普通函数一样来调用,调用这个函数,并不执行,返回的也不是函数运行的结果,而是一个指向内部状态的指针对象,也就是一个遍历器对象。
下一步,必须调用next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一条yield语句(或return语句)为止,
调用next()方法,会返回一个包括value属性和done属性的一个对象。
hw.next();
// {value:'hello',done:false}
//这个value的值就是yield语句的值,done属性的值false表示遍历还没有结束
hw.next();
// {value:'world',done:false}
hw.next();
//{value:'ending',done:true};
hw.next();
//{value:undefined,done:true};
换言之,Generator函数是分段执行的,yield语句是暂停执行的标记,而next方法可以恢复执行。
注意:Generator函数返回的是一个遍历器对象,代表Generator函数的内部指针,以后每次调用这个函数,都会返回带有value和done两个属性的一个对象、
yield语句
1.实际上yield语句是一个暂停标志。
2.yield语句和return语句在Generator函数中的区别
(1)yield语句可以在这个函数中执行多次,我的理解就是,在编写这个函数的时候,可以写多条yield语句,而return语句只能有一条。
(2)yield语句可以使Generator函数获取到多个值,即生成一系列的值。
(3)yield语句可以暂停执行,当执行next方法的时候,可以使函数从上一句yield语句停下的地方开始执行,直到下一个yield语句。而return没有位置记忆功能。
需要注意的是,yield语句后面的表达式,只有当调用next方法、内部指针才会指向该语句时才会执行,因此等于为JavaScript提供手动的“惰性求值”的语法功能。
function* gen(){
yield 123+456;
}
3.Generator函数也可以不用yield语句,这时候变成了一个单纯的暂缓执行函数。
function* f(){
console.log("ffff");
}
var generator = f();
setTimeout(function(){
generator.next();
},2000);
4.还有需要注意的是,yield语句不能用在普通函数中,否则会报错。
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;//这里面不应该使用yield,因为forEach的参数是一个普通函数。
}
})
};
//解决这个错误的方法有
将forEach改为for循环
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
}
5.yield语句用在表达式中,必须要用括号括起来。
6.yield用在函数参数或者是赋值等式的右边时,不需要用括号。
next方法的参数
1.yield语句本身没有返回值,要有值,也是undefined。所以为了赋予yield语句值,所以就让next方法有了参数。
2.next方法有了参数之后,因为Generator函数需要调用next方法来返回yield语句后面的值,这时候调用有参数的next方法之后,这个参数就会被当做上一个yield语句的返回值,注意是yield语句的返回值,而不是yield后面的值。
3.之前说了yield语句可以用于表达式中,所以有参的next方法可以为表达式中的yield语句传值。
function* foo(x){
var y = 2*(yield(x+1));
var z = yield(y/3);
return (x+y+z);
}
var a = foo(5);
a.next();// {value:6,done:false}
a.next(12) // {value:8,done:false}
a.next(13) // {value:42,done:true}
4.注意:由于next方法的参数表示的是上一条yield语句的返回值,所以第一条next语句默认没有参数,V8引擎直接忽略第一次使用next方法时的参数,从语义上来说,第一个next方法用来启动遍历器对象,所以不用带参数。
但是如果实在想在第一条语句中传参,并且能够有输入值,可以在Generator函数外面包一层,相当于先在这个包裹的这一层执行next()方法,用来启动遍历器对象。
//定义一个普通的函数,用来包裹Generator函数。
function wrapper(generatorFunction){
return function(...args){
let generatorObject = generatoraFunction(...args);
generatorObject.next();//先执行这个next
return generatorObject;
}
}
const wrapped = wrapper(function* (){
console.log(`First input:${yield}`);
return 'DONE';
})
wrapped.next('hello');//First input: hello,再执行这个next,并把hello这个值赋给yield
Generator函数(一)的更多相关文章
- ES6 - Note7:Generator函数
Generator函数 1.Generator函数是ES6增加的异步编程解决方案之一,与普通的函数行为完全不同,类似于一个状态机,内部封装了多个状态. 在函数定义的形式上,跟普通函数差不多,有两处不同 ...
- Generator 函数学习笔记
// 使用 function* 定义一个 generator 函数 function* helloWorldGenerator() { yield 'hello'; // yield 关键字作为暂停的 ...
- Generator 函数的含义与用法
Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行). function* gen(x){ var y = yield x + 2; return y; } ...
- generator函数
function* helloWordGenerator() { yield "hello"; yield "world"; return "endi ...
- ES6入门之Generator函数
Generator Generator函数是ES6提供的一种异步编程解决方案,Generator函数是一个状态机,封装了多个内部状态. 执行Generator函数会返回一个遍历器对象,也就是说,Gen ...
- 转: 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提供的一种异步编程解决方案,语法行为与传统函数完全不 ...
随机推荐
- linux编程之共享内存
linux 进程间通信(IPC)包括3种机制:消息队列.信号量.共享内存.消息队列和信号量均是内核空间的系统对象,经由它们 的数据需要在内核和用户空间进行额外的数据拷贝:而共享内存和访问它的所有应用程 ...
- java的应用项目
elk是一个不错的日志分析系统 mycat 是一不错的mysql中间件,可以做一个横向的分库分表模型,在无感知的时候,增加分库分表. apache ant 是一个java项目发布工具 springb ...
- JavaScript里的小妖精
JavaScript里的小妖精———this!! 关于this指向这个问题,活生生折磨了我一个下午,回来静下心捋顺一下,总结出来一下规律. 当然,this这个复杂的问题不是一句两句可以说清楚,作为菜鸟 ...
- 【VIPM技巧】多版本LabVIEW无法连接问题
前言 今天小编突然用到一个Toolkit,遂去VIPM上搜索,虽然可以找到但是无法连接成功LabVIEW,配置好一阵才解决.这里记录一下整个思路,供需要的人参考 问题记录 VIMP连接超时 问题解决 ...
- [hadoop][会装]hadoop ha模式安装
1.简介 2.X版本后namenode支持了HA特性,使得整个文件系统的可用性更加增强. 2.安装前提 zookeeper集群,zookeeper的安装参考[hadoop][会装]zookeeper安 ...
- kafka 设置消费者线程数
http://blog.csdn.net/derekjiang/article/details/9053863 分布式发布订阅消息系统 Kafka 架构设计 - 目前见到的最好的Kafka中文文章 M ...
- 【转载】Web开发技术发展历史-版本2
原文在这里. Web开发的发展史 导读:Arunr 把过去 15 年以来,Web开发从最初的纯 HTML 到 CGI.PHP\JSP\ASP.Ajax.Rails.NodeJS 这个过程简要地进行了介 ...
- 半透明AlphaBlend
AlphaBlend 函数功能:该函数用来显示透明或半透明像素的位图. 函数原型: BOOL AlphaBlend( HDC hdcDest, // handle to destination DC ...
- Python基础系列----序列(列表、元组、字符串)
1.定义 1 ...
- 解决CentOS7 firefox崩溃问题
现象:我在博客园写随笔的时候插入图片,每次都会崩溃,百度了好久,发现这个方法还挺好用的 在终端敲入如下命令: setsebool -P unconfined_mozilla_plugin_transi ...