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),然而网上搜到的很多教程和例子都是 ...
随机推荐
- 从零开始学安全(七)●Linux基础命令学习笔记
halt 关机reboot 现在重新启动su - 如果当前是普通用户,则输入这条命令切换到管理员用户(root),如果要切换到其他用户则敲入 su - 用户名 如: su - wangxin root ...
- EChart中使用地图方式总结(转载)
EChart中使用地图方式总结 2018年02月06日 22:18:57 来源:https://blog.csdn.net/shaxiaozilove/article/details/79274772 ...
- JSJ——主数据类型和引用
变量有两种:primitive主数据类型和引用. Java注重类型.它不会让你做出把长颈鹿类型变量装进兔子类型变量中这种诡异又危险的举动——如果有人对长颈鹿调用“跳跃”这个方法会发生什么悲剧?并且它也 ...
- 异常:getHibernateFlushMode is not valid without active transaction; nested exception is org.hibernate.HibernateException: getHibernateFlushMode is not valid without active transaction getHibernateFlu
场景: 在使用spring整合hibernate调用的HibernateTemplate时报错解决: 在spring配置文件中添加事务的配置 <bean id="hibernateTr ...
- Human Motion Analysis with Wearable Inertial Sensors——阅读2
Human Motion Analysis with Wearable Inertial Sensors 实时人体运动跟踪已经应用于生物医学领域的许多应用:临床步态分析,运动康复,跌倒检测,关节生物力 ...
- Salesforce 大量数据部署的最佳实践
本文参考自官方文档.原文链接 大量数据部署对Salesforce的影响 当用户需要在Salesforce中部署大量数据的时候,部署的过程往往会变慢.这时就需要架构师或开发者设计出更好的过程来提高大量数 ...
- (jQuery插件)autocomplete插件的简单例子
1.引入相应的js和css,我用到的时候是在jquery-ui的js里面整合的,ui的css 2.先在html上写一个input <input id="tags" class ...
- canvas代替imgage,可以有效的提高大图片加载的速度!
//加载zepto插件 <script> //定义图片的数量 var total = 17; //获取屏幕的宽度 var zWin = $(window); //定义渲染图片的方法 var ...
- mysql之代码执行结构
本文内容: 什么是代码执行结构 顺序结构 分支结构 循环结构 首发日期:2018-04-18 什么是代码执行结构: 这里所说的代码执行结构就是多条sql语句的执行顺序. 代码执行结构主要用于触发器.存 ...
- Python lambda介绍
转自:http://www.cnblogs.com/evening/archive/2010/03/29/2423554.html Python lambda 介绍 在学习python的过程中,l ...