定义
生成器对象是由一个 generator function 返回的,并且它符合可迭代协议和迭代器协议。
语法
function* gen() {
yield 1;
yield 2;
}
let g = gen();
// "Generator { }"
使用
Generator通过 next() return() 和 throw() 三个方法返回对应值。
Generator.prototype.next()
next() 方法返回一个包含属性 done 和 value 的对象。该方法也可以通过接受一个参数用以向生成器传值。
语法:gen.next(value)
参数:value:向生成器传值
返回值:返回的对象包含两个属性:
- done (布尔类型) - 如果迭代器超过迭代序列的末尾,则值为 true。 在这种情况下,value 可选地指定迭代器的返回值。
如果迭代器能够生成序列中的下一个值,则值为 false。 这相当于没有完全指定 done 属性。 - value - 迭代器返回的任意的 JavaScript 值。当 done 的值为 true 时可以忽略该值。
示例:
function* gen() {
let value = yield;
yield 1;
yield 2;
}
let g = gen(); // "Generator { }"
g.next(); // "Object { value: 1, done: false }"
g.next(); // "Object { value: 2, done: false }"
g.next(); // "Object { value: undefined, done: true }"
向生成器传值,使用值调用 next,注意因为生成器最初没有产生任何结果,所以第一次调用没有记录任何内容。
function* gen() {
while(true) {
var value = yield null;
console.log(value);
}
}
let g = gen();
g.next(1);
// "{ value: null, done: false }"
g.next(2);
// 2
// "{ value: null, done: false }"
Generator.prototype.return()
return() 方法返回给定的值并结束生成器。
语法:gen.return(value)
参数:value:需要返回的值。
返回值:返回该函数参数中给定的值。
示例:
function* gen() {
yield 1;
yield 2;
}
let g = gen();
g.next(); // { value: 1, done: false }
g.return("stop"); // { value: "stop", done: true }
g.next(); // { value: undefined, done: true },return后再调用next时value已经undefined,因为生成器已结束。
如果对已经处于“完成”状态的生成器调用return(value),则生成器将保持在“完成”状态。如果没有提供参数,则返回对象的value属性与示例最后的.next()方法相同。如果提供了参数,则参数将被设置为返回对象的value属性的值。
function* gen() {
yield 1;
}
var g = gen();
g.next(); // { value: 1, done: false }
g.next(); // { value: undefined, done: true }
g.return(); // { value: undefined, done: true }
g.return("done"); // { value: "done", done: true }
Generator.prototype.throw()
throw() 方法用来向生成器抛出异常,并恢复生成器的执行,返回带有 done 及 value 两个属性的对象。
语法:gen.throw(exception)
参数:exception:用于抛出的异常。
返回值:返回的对象包含两个属性:
- done (布尔类型) - 如果迭代器超过迭代序列的末尾,则值为 true。 在这种情况下,value 可选地指定迭代器的返回值。
如果迭代器能够生成序列中的下一个值,则值为 false。 这相当于没有完全指定 done 属性。 - value - 迭代器返回的任意的 JavaScript 值。当 done 的值为 true 时可以忽略该值。
示例:
在生成器中使用 throw 方法向该生成器抛出一个异常,该异常通常可以通过 try…catch 块进行捕获。
function* gen() {
while(true) {
try {
yield 1;
} catch(e) {
console.log("Error caught!");
}
}
}
let g = gen();
g.next(); // { value: 1, done: false }
g.throw(new Error("Something went wrong")); // "Error caught!"
使用场景
实现 Iterator,为不具备 Iterator 接口的对象提供遍历方法。
示例:{} 原生对象是不具备 Iterator 接口无法通过 for… of遍历。用 Generator 函数为其添加 Iterator 接口,使之可以遍历。
function* objectEntries(obj) {
const propKeys = Reflect.ownKeys(obj);
for (const propKey of propKeys) {
yield [propKey, obj[propKey]];
}
}
const myName = { first: 'Bob', last: 'CP' };
for (const [key,value] of objectEntries(myName)) {
console.log(`${key}: ${value}`);
}
// first: Bob
// last: CP
参考:
1.《Generator - JavaScript | MDN》;
2.《5.2 ES6 Generator 函数 | 菜鸟教程》;