您的位置:首页 > 其它

16.1.0 generator函数的语法

2018-01-15 11:24 211 查看

16.1.1 基本概念

一:generator是ES6提供的一种异步编程解决方案,执行语法跟传统函数完全不同;

二:(1)语法上看,理解成一个状态机,封装了多个内部状态;

(2)形式上看,generator是一个普通的函数,但是具备2个特征:

A:星号

B:函数体内可以使用多个yield语句定义不同的内部状态;



1:执行generator函数会返回一个遍历器对象;也就是说generator函数除了是一个状态机,还是一个遍历器对象生成函数;返回的的遍历器对象的next方法也是一个对象:如下:

{
value: ,  //yield语句后面的值或者undefined
done:  //表示是否执行完毕;true或者false
}


2:可以用next方法依次遍历generator函数内部的每个状态;

function* gen(x){
var y = yield x + 2;
var z = yield y + 2;
var p = yield 3 + 2;
yield p
return z;
}
var g = gen(1);
console.log(g) // {}
console.log(g.next()) // { value: 3, done: false }
console.log(g.next()) // { value: NaN, done: false }
console.log(g) // {}
console.log(g.next()) // { value: 5, done: false }
console.log(g.next()) // { value: undefined, done: true }
console.log(g) // {}


3:下面的写法直接报错

function gen(x){
//     yield let y =  x + 2;    //直接报错
//      var z = yield y + 2;  //直接报错
//     yield z
//     return z;
// }


注:第一次调用next后,y的值并不是3;所以第二次next以后,返回NaN;

4:由于ES6并没有规定星号出现的位置,因此下面的写法都是正确的,一般用第三种;

function * gen(x){}
function *gen(x){}
function* gen(x){}
function*gen(x){}


三:generator中的代码不会立即执行,只有第一次调用next方法才会执行第一行代码;下面的代码2秒钟执行才会打印结果

function* gen() {
console.log('ok')
}
var generator=gen()
setTimeout(function () {
generator.next()
},2000)


16.1.2 yield表达式

一:遍历器对的next方法的运行逻辑如下:

1:遇到yield语句就暂停执行后面的操作,并且将紧跟在yield后的表达式的值作为返回的遍历器对象的value值;done返回false

2:下一次调用next方法时,继续往下执行,直到遇到下一条yield语句;done返回false

3:如果没有遇到yield语句,就一直运行到函数结束;直到return语句;并且将return语句后面表达式的值作为返回对象的value值

4:如果没有return语句,就将返回对象的value值返回undefined;done返回true

二:yield不能用在其他普通函数中;不然会报错

var arr = [1, [[2, 3], 4], [5, 6]]
//语法错误:普通函数中使用yield表达式
// var flat = function* (a) {
//     a.forEach(function (item) {
//         if (typeof item !== 'number') {
//             yield* flat(item)
//         } else {
//             yield item
//         }
//     })
// }


下面的代码才是正解

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)
}


三:yield表达式如果在另外一个表达式中,必须放在()中

function* deom() {
// console.log('hello'+ yield )    //SyntaxError
// console.log('hello'+ yield 123)  ///SyntaxError

console.log('hello'+ (yield) )
console.log('hello'+ (yield 123))
}


16.1.3 generator根iterator的关系

1:任何一个对象的Symbol.inetrator方法=该对象的遍历器对象生成函数;调用该函数返回该对象的一个遍历器对象

2:由于generator函数就是遍历器生成函数,因此可以把generator复制给对象的Symbol.iterator属性,从而使得改对象具有Iterator接口;该接口可以被…运算符遍历

var myIterable = {}
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
}
console.log(myIterable)   //{ [Symbol(Symbol.iterator)]: [GeneratorFunction] }
console.log(...myIterable) //1 2 3


3:generator函数执行后返回的遍历器对象,也具有Symbol.inetrator属性,执行后返回自身;

function* gen() {
}
var g=gen()
console.log(g[Symbol.iterator]()===g)  //true
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: