generator函数
来源:互联网 发布:移动宽带端口限制 编辑:程序博客网 时间:2024/05/29 12:12
一、generator函数
1.对于generator函数的定义和相关的作用及语法
Generator函数是ES6提供的一种异步编程解决方案
Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。
形式上,Generator函数是一个普通函数,但是有两个特征。一是,function
关键字与函数名之间有一个星号;二是,函数体内部使用yield
语句,定义不同的内部状态.(yield语句不能再非generator函数中使用,否则会报错)
2.generator函数的简单使用
Generator函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用Generator函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象
必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next
方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield
语句(或return
语句)为止。
eg:
function* test() { yield 'this is'; yield 'a test'; return 'ending';}var t = test();
t.next()// { value: 'this is', done: false }t.next()// { value: 'a test', done: false }t.next()// { value: 'ending', done: true }t.next()// { value: undefined, done: true }
当done的值为true以后以后调用next()方法返回相同的值每次调用遍历器对象的next
方法,就会返回一个有着value
和done
两个属性的对象。value
属性表示当前的内部状态的值,是yield
语句后面那个表达式的值;done
属性是一个布尔值,表示是否遍历结束。
generator函数的“*”与方法之间可以有空格,也可以都没有,没有明确的规定(一般写在紧跟function以后,eg:function* test(){...})
yield语句:
其实提供了一种可以暂停执行的函数。yield
语句就是暂停标志。
(1)遇到yield
语句,就暂停执行后面的操作,并将紧跟在yield
后面的那个表达式的值,作为返回的对象的value
属性值。
(2)下一次调用next
方法时,再继续往下执行,直到遇到下一个yield
语句。
(3)如果没有再遇到新的yield
语句,就一直运行到函数结束,直到return
语句为止,并将return
语句后面的表达式的值,作为返回的对象的value
属性值。
(4)如果该函数没有return
语句,则返回的对象的value
属性值为undefined
。
node命令行测试
function* test(){yield 'name = lcl'; yield 'age = 23'; return 'ending'};
var generator = test();
generator.next() //{ value: 'name = lcl', done: false }
yield
语句如果用在一个表达式之中,必须放在圆括号里面。
console.log('Hello' + yield 123); // SyntaxErrorconsole.log('Hello' + (yield 123)); // OK
yield 与 Iterator接口的关系:
任意一个对象的Symbol.iterator
方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。
由于Generator函数就是遍历器生成函数,因此可以把Generator赋值给对象的Symbol.iterator
属性,从而使得该对象具有Iterator接口。
var myIterable = {};myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 3;};[...myIterable] // [1, 2, 3]
上面代码中,Generator函数赋值给Symbol.iterator
属性,从而使得myIterable
对象具有了Iterator接口,可以被...
运算符遍历了。next() 方法的参数
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() // Object{value:6, done:false}a.next() // Object{value:NaN, done:false}a.next() // Object{value:NaN, done:true}var b = foo(5);b.next() // { value:6, done:false }b.next(12) // { value:8, done:false }b.next(13) // { value:42, done:true }
上面代码中,第二次运行next
方法的时候不带参数,导致y的值等于2 * undefined
(即NaN
),除以3以后还是NaN
,因此返回对象的value
属性也等于NaN
。第三次运行Next
方法的时候不带参数,所以z
等于undefined
,返回对象的value
属性等于5 + NaN + undefined
,即NaN
。
如果向next
方法提供参数,返回结果就完全不一样了。上面代码第一次调用b
的next
方法时,返回x+1
的值6;第二次调用next
方法,将上一次yield
语句的值设为12,因此y
等于24,返回y / 3
的值8;第三次调用next
方法,将上一次yield
语句的值设为13,因此z
等于13,这时x
等于5,y
等于24,所以return
语句的值等于42。
注意,由于next
方法的参数表示上一个yield
语句的返回值,所以第一次使用next
方法时,不能带有参数。V8引擎直接忽略第一次使用next
方法时的参数,只有从第二次使用next
方法开始,参数才是有效的。从语义上讲,第一个next
方法用来启动遍历器对象,所以不用带有参数。
使用generator函数 结合for...of 遍历普通对象的方法
1、给普通对象添加Symbol.iterator(该iterator由generator函数返回)
2、使用for...of 遍历对象
下面是不同的两种方法给普通对象添加Symbol.iterator
利用for...of
循环,可以写出遍历任意对象(object)的方法。原生的JavaScript对象没有遍历接口,无法使用for...of
循环,通过Generator函数为它加上这个接口,就可以用了。
function* objectEntries(obj) { let propKeys = Reflect.ownKeys(obj); for (let propKey of propKeys) { yield [propKey, obj[propKey]]; }}let jane = { first: 'Jane', last: 'Doe' };for (let [key, value] of objectEntries(jane)) { console.log(`${key}: ${value}`);}// first: Jane// last: Doe
上面代码中,对象jane
原生不具备Iterator接口,无法用for...of
遍历。这时,我们通过Generator函数objectEntries
为它加上遍历器接口,就可以用for...of
遍历了。加上遍历器接口的另一种写法是,将Generator函数加到对象的Symbol.iterator
属性上面。
function* objectEntries() { let propKeys = Object.keys(this); for (let propKey of propKeys) { yield [propKey, this[propKey]]; }}let jane = { first: 'Jane', last: 'Doe' };jane[Symbol.iterator] = objectEntries;for (let [key, value] of jane) { console.log(`${key}: ${value}`);}// first: Jane// last: Doe
generator函数的throw()方法的使用
generator函数的return()方法的使用
详细见:http://es6.ruanyifeng.com/#docs/generator
yield* 语句
如果在Generater函数内部,调用另一个Generator函数,默认情况下是没有效果的。
这个就需要用到yield*
语句,用来在一个Generator函数里面执行另一个Generator函数。
- generator函数
- Generator函数
- generator函数
- generator函数
- Generator 函数
- Generator函数
- Generator函数
- ES6 Generator函数
- es6的Generator函数
- ECMAScript6笔记:Generator 函数
- 第十四节,Generator 函数
- Generator 函数 - 基本概念
- ES6中的Generator函数
- 箭头函数 generator
- JavaScript--Generator函数
- ECMAScript6(13):Generator 函数
- 生成器函数(generator)
- Generator函数基础
- libcurl 使用 链接错误
- 深入浅出 RPC - 深入篇
- mysql5.7安装版my.ini配置文件路径
- iOS提交问题:您的 App 正在使用广告标识符 (IDFA)
- C#修改引用dll的相对路径
- generator函数
- 微信小程序 开发 微信开发者工具 快捷键
- oracle数据库连接 ORA-12638:身份证明检索失败
- JAVA学习 002 --java 包使用(入门)
- Diagonalify
- 中日流行句
- 用友T3的常见下载地址及问题解决(精华)
- javaCV开发详解之6:本地音频(话筒设备)和视频(摄像头)抓取、混合并推送(录制)到服务器(本地)
- 腾讯云ubuntu tomcat 运行速度慢!!