您的位置:首页 > 其它

ES6学习——生成器(Generators):详细语法

2016-01-26 11:02 369 查看
先看一下生成器的几种声明方法:

function* genFunc() {}//函数声明
let genObj = genFunc();


const genFunc = function* () { };//函数表达式
let genObj = genFunc();


let obj = {//对象字面量
* generatorMethod() {
}
};
let genObj = obj.generatorMethod();


class MyClass {//类方法
* generatorMethod() {
}
}
let myInst = new MyClass();
let genObj = myInst.generatorMethod();


上面创建生成器实例的时候我们并没有使用new操作符,而且直接当函数来调用,规范中明确说明了,用和不用new的效果是一样的:

The GeneratorFunction constructor is the %GeneratorFunction% intrinsic. When GeneratorFunction is called as a function rather than as a constructor, it creates and initializes a new GeneratorFunction object. Thus the
function call GeneratorFunction (…) is equivalent to the object creation expression new GeneratorFunction (…) with the same arguments.


然后在看看yield的一些语法:
yield只能直接使用在生成器函数中:

function* genFunc() {
['a', 'b'].forEach(x => yield x); // Uncaught SyntaxError: Unexpected strict mode reserved word
}
上面这个yield是用在了forEach的回调函数中,并没有直接在生成器函数中,所以会报错。下面这种写法就是OK的:

function* genFunc() {
for (let x of ['a', 'b']) {
yield x;
}
}


yield是个关键字,不是操作符,虽然(yield 3)这种写法看起来像个操作符,但是yield还可以用作赋值操作(var x = yield),这点明显看出它不像个操作符。

yield的优先级很低,所以有一些写法需要特殊注意:

function* genFunc() {
yield 3;
var a = 2 + yield 3; //这种写法是错误的
var b = 2 + (yield 3); //加括号就OK了
}


yield 2 + 3;//等同于yield (2+3)
(yield 2) + 3;
所以在不确定yield优先级的情况下,最好加上括号,这样能保证不出错。yield的结合性是右结合:

yield yield yield 3//等同于yield (yield (yield 3))


yield还可以直接当作函数参数来使用:

foo(yield 'a', yield 'b');


上面林林总总说了一些yield的语法,下面看yield起的作用:

yield主要用途:1)生产数据,2)接收数据

1)生产数据,这个作用大家肯定不陌生,上面的绝大部分例子都是这个作用。就是用next函数调用时,返回的结果中value值就是yield后面跟的数据

function* genFunc() {
yield 3;
}

var g = genFunc();
console.log(g.next());//Object {value: 3, done: false}


2)接收数据,这个用途还没有看到过具体的例子,其实把yield赋值给一个变量就是这种用法。

function* genFunc() {
var b = 2 + (yield 3);
console.log(b);//7
}

var g = genFunc();
g.next()//这里不能省略,相当于让yield先产生数据
g.next(5);//yield接收数据


在往深了看一下,生产数据起到数据生产者的作用,接收数据起到数据消费者的作用。可以看出yield能衍生出很复杂的用法,以后的文章中在详细介绍。

生成器还有一个用法是可以有返回值的,生成器的返回值作为done为true时的value值:

function *foo() {
yield 1;
return 4;
}

var g = foo();
console.log(g.next());//Object {value: 1, done: false}
console.log(g.next());//Object {value: 4, done: true}


*以上全部代码在Chrome 48下通过测试
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: