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);
posted @   梦呓qwq  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示