JavaScript生成器

生成器基础

当调用 Generator 函数时,它不会立即执行,而是返回一个称为 Generator 对象的迭代器。通过调用该迭代器的 next() 方法,可以逐步执行 Generator 函数的代码,并在遇到 yield 关键字时暂停函数的执行,并返回一个包含当前状态的对象。

每次调用 next() 方法时,Generator 函数会从上一个 yield 语句的位置继续执行,直到遇到下一个 yield 或者函数结束。在执行过程中,可以通过 yield 关键字将一个值传递给调用方。

function* loggerator() {
  console.log("开始执行");
  yield "stop";
  console.log("继续执行");
  return "done";
}

let logger = loggerator();
console.log(logger.next());
console.log(logger.next());

第一次调用 next()方法时,生成器函数会执行到第一个 yield的位置然后暂停执行,并把对应的值放在 value中返回,此时函数还没有 return,所以 done的值为 false

第二次调用 next()方法时,生成器函数从第三行开始执行,在 return语句处结束执行。函数返回值同样被放在 value属性中,但因为此时函数的运行已经结束了,所以 done的值为 true

因为生成器对象实现了迭代器协议,所以我们可以通过 for...of循环和扩展运算符来对其进行操作。

function* loggerator() {
  console.log("开始执行");
  yield "stop";
  console.log("继续执行");
  return "done";
}

let logger = loggerator();
for (let value of logger) {
  console.log(value);
}

yield 表达式除了可以返回一个值之外,还可以用来接收外部传入的值。当调用 Generator 对象的 next() 方法时,可以通过传递参数将值传递给 Generator 函数内部的 yield 表达式。

第一个 next()方法中传入的值会被忽略,这是因为此时函数才刚刚开始执行,还没有遇到任何 yield可以接收输入值,函数会在 let msg = yield处停止执行,因为遇到了 yield关键字。通过调用 next方法可以带一个参数,该参数就会被当作上一个 yield表达式的返回值。

function* genFunc() {
  console.log("Hello I am hearing");
  while (true) {
    let msg = yield;
    console.log(`I heard ${msg}`);
  }
}

let gen = genFunc();
gen.next();
gen.next("Hello");
gen.next("I am Jack");

递归生成器

yield* 是 JavaScript 中的一种语法,用于在 Generator 函数内部委托(delegate)执行另一个可迭代对象或 Generator 函数的迭代过程。

使用 yield* 语法可以将迭代控制权交给另一个可迭代对象,并从中产生值。它的语法形式为 yield* expression,其中 expression 是一个可迭代对象或 Generator 函数。

当执行 yield* expression 时,会在 Generator 函数内部暂停当前的迭代过程,并将控制权转移到 expression 所代表的迭代对象或 Generator 函数上。迭代对象或 Generator 函数生成的值会被逐个返回给调用方。

class TreeNode {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
    // ! 先序遍历
    *[Symbol.iterator]() {
        yield this.data;
        /**
         * 执行 yield* expression 时,会在 Generator 函数内部暂停当前的迭代过程,
         * 并将控制权转移到 expression 所代表的迭代对象或 Generator 函数上。
         * 迭代对象或 Generator 函数生成的值会被逐个返回给调用方。
         */
        if (this.left) yield* this.left;
        if (this.right) yield* this.right;
    }
}

let root = new TreeNode(1);
root.left = new TreeNode(2);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right = new TreeNode(3);
root.right.left = new TreeNode(6);
root.right.right = new TreeNode(7);
/**
 *    1
 *  2   3
 * 4 5 6 7
 */

// console.log([...root]);
for (let node of root) {
    console.log(node);
}

异步生成器

异步生成器(Async Generator)是指使用异步函数定义的生成器函数。异步生成器函数可以使用 async 关键字声明,并在函数体内部使用 yield 关键字来暂停执行并产生值。

异步生成器函数与普通生成器函数的区别在于,异步生成器函数可以在 yield 表达式中使用异步操作(如异步函数调用、Promise 等),并通过 await 关键字来等待异步操作的完成。

定义了一个异步生成器函数 asyncGenerator。它使用 async function* 语法声明,表明该函数是一个异步生成器函数。

在函数体内部,我们使用 yield 关键字产生了三个值:'Hello''Async''Generator'。在 yield 'Hello' 后面,我们使用 await 关键字等待一个模拟的异步操作 delay(1000) 的完成,以模拟异步操作的延迟。

delay 函数返回一个 Promise,它会在指定的毫秒数后解析。通过使用 await 关键字,异步生成器函数会等待 Promise 的解析结果,并在解析完成后继续执行。

main 函数中,我们创建了一个异步生成器对象 generator,并通过调用 next() 方法来逐步获取异步生成器产生的值。我们使用 await 关键字来等待每个 next() 方法的结果。

async function* asyncGenerator() {
  yield 'Hello';
  await delay(1000); // Simulating an asynchronous operation
  yield 'Async';
  yield 'Generator';
}

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function main() {
  const generator = asyncGenerator();

  console.log(await generator.next()); // { value: 'Hello', done: false }

  await delay(2000); // Simulating a delay

  console.log(await generator.next()); // { value: 'Async', done: false }
  console.log(await generator.next()); // { value: 'Generator', done: false }

  console.log(await generator.next()); // { value: undefined, done: true }
}

main();
  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值