本文内容主要来自《深入浅出ES6》
ES6生成器不是指生成ES代码的机器。
示例代码:
先看一段示例:
function* quips(name) {
yield "你好 " + name + "!";
yield "希望你能喜欢这篇介绍 ES6 的译文";
if (name.startsWith("X")) {
yield "你的名字 " + name + " 首字母是 X,这很酷!";
}
yield "我们下次再见!";
}
生成器函数和普通函数的区别
这段代码看起来很像一个函数,我们称之为生成器函数,它与普通函数有很多共同点,但是二者有如下区别:
- 普通函数使用 function 声明,而生成器函数使用 function*声明。
- 在生成器函数内部,有一种类似 return 的语法:关键字 yield。
二者的区别是,普通函数只可以 return 一次,而生成器函数可以 yield 多次(当然也可以只 yield 一次)。 在生成器的执行过程中,遇到 yield 表达式立即暂停,后续可恢复执行状态。
这就是普通函数和生成器函数之间最大的区别,普通函数不能自暂停,生成器函数 可以。
生成器函数的执行
上面那段函数的执行:
> var iter = quips("jorendorff");
[object Generator]
> iter.next()
{ value: "你好 jorendorff!", done: false }
> iter.next()
{ value: "希望你能喜欢这篇介绍 ES6 的译文", done: false }
> iter.next()
{ value: "我们下次再见!", done: false } > iter.next()
{ value: undefined, done: true }
你大概已经习惯了普通函数的使用方式,当你调用它们时,它们立即开始运行,直 到遇到 return 或抛出异常时才退出执行。
生成器调用看起来非常类似:quips("jorendorff")。但是,当你调用一个生成器时,它并非立即执行,而是返回一个已暂停的生成器对象(上述实例代码中的 iter)。你可 将这个生成器对象视为一次函数调用,只不过立即冻结了,它恰好在生成器函数的最顶 端的第一行代码之前冻结了。
每当你调用生成器对象的.next()方法时,函数调用将其自身解冻并一直运行到下一 个 yield 表达式,再次暂停。
这也是在上述代码中我们每次都调用 iter.next()的原因,我们获得了 quips()函数体 中 yield 表达式生成的不同的字符串值。
调用最后一个 iter.next()时,我们最终抵达生成器函数的末尾,所以返回结果中 done 的值为 true。抵达函数的末尾意味着没有返回值,所以返回结果中 value 的值为 undefined。
如果用专业术语