ES5-ES6-ES7_Generator 函数
Generator函数的概述
Generator 函数是 ES6 提供的一种异步编程解决方案
Generator函数指的是一种新的语法结构,是一个遍历器对象生成器,它内部可以封装多个状态,很适合用于异步操作
Generator函数语法和普通的function函数类似,但是有三个不同点:
(1)function关键字和函数名称之间有一个星号(*)。
(2)函数体内可以使用yield语句。 可暂停函数(惰性求值), yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
(3)函数调用后不会立即执行,返回的是一个遍历器对象
现实业务应用中,Generator的优点是可以等第一条请求发送成功之后,拿到数据在发送第二条请求,缺点是没有脱离回调函数
function* helloWorldGenerator() {
console.log('aaaaaaaaaa')
yield 'hello';
console.log('bbbbbbbbbb')
yield 'world';
console.log('ccccccccccc')
return 'ending';
} let hw = helloWorldGenerator();//调用此函数,并不会立即执行它其中的代码,而是返回一个遍历器对象 也就是指向内部状态的指针对象 // 必须调用遍历器对象的next方法,使得指针移向下一个状态。
// 也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。
// 换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。 // 第一次调用,Generator 函数开始执行,直到遇到第一个yield表达式为止。
// next方法返回一个对象,它的value属性就是当前yield表达式的值hello,done属性的值false,表示遍历还没有结束。
console.log(hw.next()) //{ value: 'hello', done: false }
console.log(hw.next()) //{ value: 'world', done: false }
console.log(hw.next()) //{ value: 'ending', done: true }
console.log(hw.next()) //{ value: undefined, done: true }
console.log(hw.next()) //{ value: undefined, done: true }
创建Generator函数
Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。
不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象
函数内部使用yield语句定义不同的状态,return也可以定义一个状态
每个yield语句定义不同的状态,它也是一个代码执行暂停标识,yield语句不能在普通函数中使用,否则会报错。
// 定义了一个 Generator 函数helloWorldGenerator,它内部有两个yield表达式(hello和world)
// 即该函数有三个状态:hello,world 和 return 语句(结束执行)
function* helloWorldGenerator() {
console.log('aaaaaaaaaa')
yield 'hello';
console.log('bbbbbbbbbb')
yield 'world';
console.log('ccccccccccc')
return 'ending';
} let hw = helloWorldGenerator();//调用此函数,并不会立即执行它其中的代码,而是返回一个遍历器对象 也就是指向内部状态的指针对象 console.log(hw.next()) //{ value: 'hello', done: false },返回一个具有value和done属性的对象
console.log(hw.next()) //{ value: 'world', done: false }
console.log(hw.next()) //{ value: 'ending', done: true } ,有return,返回{value:ending,done:true}
console.log(hw.next()) //{ value: undefined, done: true },没有return,返回{value: undefined, done: true}
console.log(hw.next()) //{ value: undefined, done: true }
yield语句
每一个yield语句定义不同的状态,它也是一个代码执行暂停标识。
yield语句不能在普通函数中使用,否则会报错。
调用Generator函数可以返回一个遍历器对象,要想访问Generator函数中的每一个状态,需要使用遍历器对象调用next()方法
如果yield语句作为其他语句的一部分,那么必须使用小括号包裹,否则会报错
// 定义了一个 Generator 函数helloWorldGenerator,它内部有两个yield表达式(hello和world)
// 即该函数有三个状态:hello,world 和 return 语句(结束执行)
function* helloWorldGenerator() {
//console.log("欢迎来到" + yield "generator");//报错,SyntaxError: Unexpected identifier
console.log("欢迎来到" + (yield "generator"));//正确,打印出:欢迎来到undefined
yield 'hello';
return 'ending';
} let hw = helloWorldGenerator();//调用此函数,并不会立即执行它其中的代码,而是返回一个遍历器对象 也就是指向内部状态的指针对象 console.log(hw.next().value) //generator
console.log(hw.next().value) //hello
console.log(hw.next().value) //ending
next()方法
next()一个主要功能,就是从暂停状态继续下一段代码的执行。
next()还有一个重要的功能,那就是可以接受一个参数,此参数作为上一个yield语句的返回值。
虽然当代码执行到yield语句的时候,能够将其后面的表达式的值作为对象的value属性值,但是默认情况下yield语句是没有返回值的,或者说它的返回值是undefined
function* helloWorldGenerator() {
console.log("欢迎来到" + (yield "generatoraaaaaa"));
console.log("欢迎来到" + (yield "generatorbbbbbb"));
yield 'hello';
return 'ending';
} let hw = helloWorldGenerator(); console.log(hw.next('我是注入进来的aaaa')) //第1个next传值无意义,因为没有上一个yield
console.log(hw.next('我是注入进来的bbbb'))
console.log(hw.next('我是注入进来的cccc'))
console.log(hw.next())
function* yuanku(num) {
let x = 2 * (yield num);
console.log('x='+x);
let y = yield x*3;
console.log('y='+y);
console.log(x,y);
}
var g = yuanku(5);
console.log(g.next());//{value:5,done:false},第1个next传值无意义,因为没有上一个yield
console.log(g.next());//x=NaN {value:NaN,done:false}
console.log(g.next(3));//{value:12,done:false}
console.log(g.next(3));//{value:undefined,done:true}
Generator 函数应用——部署Iterable接口
普通的对象在部署iterable接口之前,是不能使用for of去遍历对象的
let obj = {
userName: 'huang',
age: 32
}
for (let i in obj){ // for in可以遍历普通对象的属性
console.log(i)
} for (let i of obj) { // for of不能遍历普通对象的属性 报错:obj is not iterator
console.log(i)
}
核心思想:可以将任何数据作为Generator函数
的参数,当我们调用Generator函数
返回的Generator类
实例对象就可以认为是参数的遍历器对象,且这个遍历器对象上还有Symbol.iterator
属性方法,方法的返回值指向遍历器对象自己
let obj = {
userName: 'huang',
age: 32
} //相当于给obj这个对象人为的部署了iterator,之后就可以使用for of进行遍历内部的状态
obj[Symbol.iterator] = function* myGenerator () {
yield 1
yield 2
yield 3
} for (let i of obj) {
console.log(i) //遍历了myGenerator函数的状态,默认就是调用next方法,分别是1,2,3
}
function* deployObjectInterface(obj){
let keys = Object.keys(obj);
console.log(keys)
for(let i=0; i<keys.length; i++){
let key = keys[i];
yield [key, obj[key]];
}
}
let obj = {name:"Cynthia", age:21 };
for(let[key, value] of deployObjectInterface(obj)){
console.log(key, value);
}
// name Cynthia
// age 21
Generator 函数应用——部署Ajax操作
模拟一个业务逻辑,首先发送一次请求,成功之后拿到请求回来的数据,再发送第二次请求(这次请求需要用到第一次请求回来的数据)
如果第一条请求没有成功,第二次请求不会触发
function getNews(url) {
$.get(url, function (data) {
console.log(data)
let url = 'http://sss:3000?id='+ data.id
SX.next(url) //第二次请求
})
} function* sendXml() {
yield getNews('http://sss:3000')
yield getNews(url)
}
let SX = sendXml()
SX.next() // 第一次请求
ES5-ES6-ES7_Generator 函数的更多相关文章
- es6的箭头函数和es5的function函数区别
一.es6的箭头函数es6箭头函数内部没有this,使用时会上朔寻找最近的this不可以做构造函数,不能使用new命令,因为没有this函数体内没有arguments,可以使用rest参数代替不能用y ...
- 简述ES5 ES6
很久前的某一天,一位大神问我,你知道ES6相对于ES5有什么改进吗? 我一脸懵逼的反问,那个啥,啥是ES5.ES6啊. 不得不承认与大神之间的差距,回来深思了这个问题,结合以前的知识,算是有了点眉目. ...
- es6箭头函数讲解
es6箭头函数的用法 箭头函数是es6的一种函数的简写方法. 如下: var f = v = > v; //等同于 var f = function(v){ return v; } var su ...
- es6箭头函数 this 指向问题
es5中 this 的指向 var factory = function(){ this.a = 'a'; this.b = 'b'; this.c = { a:'a+', b:function(){ ...
- Atitit js es5 es6新特性 attilax总结
Atitit js es5 es6新特性 attilax总结 1.1. JavaScript发展时间轴:1 1.2. 以下是ES6排名前十的最佳特性列表(排名不分先后):1 1.3. Es6 支持情况 ...
- ES6 箭头函数 this 指向
ES6 箭头函数 this 指向 箭头函数有几个使用注意点: 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个 ...
- 深入理解ES6之函数
一:关于函数的参数: 可以接受任意数量的参数而无视函数声明的参数数量是js函数的独特之处. 1:参数默认值 ES6之前做法: function makeRequest(url,timeout,call ...
- ES6入门——函数的扩展
1.函数参数的默认值 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法.现在ES6可以为函数的参数添加默认值,简洁了许多. ES5 function show(a,b){ b = b ...
- es6之函数扩展与对象扩展
一.函数扩展 1.参数默认值 参数有默认值,后面不可以再加没有默认值的变量.如以下test函数中,不可以加写成 function test(x,y="word",z){ } fun ...
- 【转】React Native中ES5 ES6写法对照
很多React Native的初学者都被ES6的问题迷惑:各路大神都建议我们直接学习ES6的语法(class Foo extends React.Component),然而网上搜到的很多教程和例子都是 ...
随机推荐
- Docker虚拟机实战
安装Docker虚拟机 ◆ 先更新yum软件管理器,然后再安装Docker #更新yum软件管理器 yum -y update #安装Docker yum install -y ...
- linux基本命令手册
常用指令 ls 显示文件或目录 -l 列出文件详细信息l(list) -a 列出当前目录下所有文件及目录,包括隐藏的a(all) mkdir ...
- ECharts中color : function的用法(转)
ECharts图表实战经验1:如何设置图表同序列不同数据点的独立颜色值 最近有不少朋友在追问这样一个问题:我单序列的柱状图,我想让每一个根柱子的颜色都不一样,应该如何做? 针对这个问题,其实我只想 ...
- 【Java每日一题】20170316
20170315问题解析请点击今日问题下方的“[Java每日一题]20170316”查看(问题解析在公众号首发,公众号ID:weknow619) package Mar2017; public cla ...
- D. GukiZ and Binary Operations(矩阵+二进制)
D. GukiZ and Binary Operations We all know that GukiZ often plays with arrays. Now he is thinking ...
- Java岗 面试考点精讲(基础篇01期)
即将到来金三银四人才招聘的高峰期,渴望跳槽的朋友肯定跟我一样四处找以往的面试题,但又感觉找的又不完整,在这里我将把我所见到的题目做一总结,并尽力将答案术语化.标准化.预祝大家面试顺利. 术语会让你的面 ...
- thinkphp——通过在线编辑器添加的内容在模板里正确显示(只显示内容,而不是html代码)
thinkphp编辑器回显问题如下: 解决办法如下: 对于编辑器发布的内容,前台模板显示为html的解决办法是: 在模板输出字段加入html_entity_decode()函数 也就是:PHP输出时的 ...
- 兼容浏览器的div透明
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- HDU1846 Brave Game
Brave Game Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- SAP MM MM17里不能修改物料主数据'Purchasing Value Key'字段值?
SAP MM MM17里不能修改物料主数据'Purchasing Value Key'字段值? 记得在D项目上线之前数据导入系统之后,业务提出一些物料采购视图里的’Purchasing value k ...