Generator
Generator
本质上相当于一个状态机,还是一个遍历器对象生成函数,可依次遍历函数内部的每一个状态。
function* hello(){
yield '1';
yield '2';
return 'ending';
}
var hw=hello();//状态转移的过程
hw.next();//{value:'1',done:false};
hw.next();//{value:'2',done:false};
hw.next();//{value:'ending',done:false};
hw.next();//{value:undefined,done:true};
function* f(){
console.log()
}
var generator=f();
setTimeout(function(){
generator.next();
},2000);
//f如果是普通函数,赋值时就会执行,f是Generator函数,在调用next方法时,函数f才会执行.
可以将遍历器生成函数赋值到对象的Symbol.iterator属性中作为Iterator接口。
var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
异步操作的同步化表达
//yield可以实现暂停效果:
function* loadUI(){
showLoading();
yield loadUIDataAsynchronously();
hideLoading();
}
var loader=loadUI();
loader.next();//执行到异步操作
loader.next();//进行异步操作后续步骤。
将回调函数改成直线执行的形式:
function* longRunning(value1){
try{
var value1=yield step1(v1);
var value2=yield step2(v2);
}catch(e){
}
}
scheduler(longRunningTask(initalValue));
function scheduler(task){
var taskObj=task.next(task.value);
if(!taskObj.done){
task.value=taskObj.value;
scheduler(task);
}
}
使用return来返回给定的值,并且终结遍历Generator函数:
function* gen(){
yield 1;
yield 2;
yield 3;
}
var g=gen();
g.next();
g.return('foo');//终止生成函数的遍历.
g.next();
//如果是try...finally就不一样了
function* numbers () {
yield 1;
try {
yield 2;
yield 3;
} finally {
yield 4;
yield 5;
}
yield 6;
}
var g = numbers();
g.next() // { value: 1, done: false }
g.next() // { value: 2, done: false }
g.return(7) // { value: 4, done: false }
g.next() // { value: 5, done: false }
g.next() // { value: 7, done: true }
next()是将yield表达式换成一个值
const g=function* (x,y){
let result=yield x+y;
return result;
}
const gen=g(1,2);
gen.next();
gen.next(1);
在生成器函数中嵌套生成器函数:
function* inner() {
yield 'hello!';
}
function* outer1() {
yield 'open';
yield inner();
yield 'close';
}
var gen = outer1()
gen.next().value // "open"
gen.next().value // 返回一个遍历器对象
gen.next().value // "close"
function* outer2() {
yield 'open'
yield* inner()
yield 'close'
}
var gen = outer2()
gen.next().value // "open"
gen.next().value // "hello!"
gen.next().value // "close"
对于yield*和yield的差别:
//如果是yield*后面跟着的是数组,就会遍历数组成员,如果是yield后面会直接返回一个数组
function* gen(){
yield* ["a","b","c"];
yield "hello";
}
gen.next();//a
gen.next();//"hello"
有return的可以返回对应的数据值:
function* foo(){
yield 2;
yield 3;
return "foo";
}
function* bar(){
yield 1;
var v=yield* foo();
console.log("v: "+v);
yield 4;
}
var it=bar();
console.log(it.next());//{value:1,done:false}
console.log(it.next());//{value:2,done:false}
console.log(it.next());//{value:3,done:false}
console.log(it.next());//{value:4,done:false}
//使用yield*可以方便得取出嵌套数组的所有成员:
function* iterTree(tree){
if(Array.isArray(tree)){
for(let i=0;i<tree.length;i++){
yield* iterTree(tree[i]);
}
}else{
yield tree;
}
}
const tree=['a',['b','c'],['d','e']];
for(let xof iterTree(tree)){
console.log(x);
}
作为对象属性的Generator函数:
let obj={
*myGenratorMethod(){
...
}
}
对于Generator函数来说返回的是一个遍历器,相当于继承,不过返回的不是this,注意和this对象区分
function* g(){}
g.prototype.hello=function(){
return 'hi!';
};
let obj=g();
obj instanceof g;//true
obj.hello()//'hi!';
//在this对象上加了一个属性a,obj对象拿不到
function* g(){
this.a=11;
}
let obj=g();
console.log(obj.next());//{value:undefined,done:true}
console.log(obj.a);//undefined
两种办法将生成器函数实现构造器的功能:
//将其绑定到obj对象上.
function* F() {
this.a = 1;
yield this.b = 2;
yield this.c = 3;
}
var obj = {};
var f = F.call(obj);
//将obj转为F.prototype
function* F() {
this.a = 1;
yield this.b = 2;
yield this.c = 3;
}
var f = F.call(F.prototype);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!