前言
学习Generators之前我们先理解一下es6的迭代器:迭代器详解
正文
什么是Generators?
生成器也是ES6新增加的一种特性。它的写法和函数非常相似,只是在声明时多了一个” * ”号。
function* say(){
}
const say = function*(){
}
注意:这个 ※ 只能写在function关键字的后面。
但是生成器和普通函数并不是只有写法上的区别,本质上,普通函数在调用后,必定执行该函数直到函数结束或者return为止,中途是不能停止的,而生成器则是可以暂停的的函数。
function* say(){
yield "开始";
yield "执行中";
yield "结束";
}
let it = say(); // 调用say方法,得到一个迭代器
console.log(it) // [object Generator]
console.log(it.next()); // { value: '开始', done: false }
console.log(it.next()); // { value: '执行中', done: false }
console.log(it.next()); // { value: '结束', done: false }
console.log(it.next()); // { value: undefined, done: true }
调用生成器的say方法,此时的函数并没有执行而得到的是一个迭代器,通过前言中迭代器的认识,我们可以知道调用迭代器next()方法,say函数开始执行,当遇到yield时,函数被挂起并返回一个对象,其中包含value属性,它的值是yield后面跟着的数据,并且done的值为false。再次执行next,函数又被激活,并继续往下执行,直到遇到下一个yield。当所有的yield都执行完了,再次调用next时得到的value就是undefined,done的值为true。
当然Generator 函数可以不用yield表达式,这时就变成了一个单纯的暂缓执行函数。
function* f() {
console.log('执行了!')
}
var generator = f();
setTimeout(function () {
generator.next()
}, 2000); //两秒后 -> "执行了!"
如果你能理解前言中的迭代器,那么此时的生成器也就很好理解了。它可以通过yield关键字将函数的执行挂起,或者理解成暂停。它的外部在通过调用next方法,让函数继续执行,直到遇到下一个yield,或函数执行完毕,它的yield,其实就是next方法执行后挂起的地方,并得到你返回的数据。
所以生成器由此可以理解为 可以暂停(暂缓执行)的函数 。
生成器的特征和自带方法
next 是否需要传参数?
下面再看一个例子
function * say(x) {
let y = 2 * (yield x)
let z = yield (y / 3)
return x+y+z
}
let it = say(5)
console.log(it.next());//{value: 5, done: false}
console.log(it.next());//{value: NaN, done: false}
console.log(it.next());//{value: NaN, done: false}
yield表达式本身没有返回值,或者说总是返回undefined。undefined+数字就返回NaN,next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
下面我们给next传入参数:
function* say(x) {