优雅而高效的JavaScript——Generator 函数

在这里插入图片描述

😎博主:小猫娃来啦
😎文章核心:优雅而高效的JavaScript——Generator 函数

什么是Generator函数

Generator函数是ES6中新增的一种函数类型,它可以用来生成迭代器对象。通过使用yield关键字在函数内部暂停和恢复代码的执行,Generator函数可以实现函数的暂停和恢复。Generator函数是一种特殊类型的函数,它可以在函数执行过程中多次返回值,并且可以通过next方法控制函数的执行。


Generator函数的基本语法

Generator函数的定义与普通函数类似,只是在函数名前面加上了一个星号(*),如下所示:

function* myGenerator() {
  // 函数体
}

在Generator函数内部,可以使用yield关键字来暂停函数的执行,并返回一个值。yield关键字可以出现在函数的任意位置,每次执行到yield语句时,函数都会暂停执行,并将yield后面的表达式的值作为返回值返回给调用者。当再次调用next方法时,函数会从上次暂停的位置继续执行,直到遇到下一个yield语句或函数结束。


Generator函数的运行机制

Generator函数的运行机制与普通函数有所不同。当调用Generator函数时,并不会立即执行函数体,而是返回一个迭代器对象。通过调用迭代器对象的next方法,可以控制Generator函数的执行。

当调用next方法时,Generator函数会执行到第一个yield语句,并将yield后面的表达式的值作为返回值返回给调用者。同时,Generator函数会暂停执行,等待下一次调用next方法。

当再次调用next方法时,Generator函数会从上次暂停的位置继续执行,直到遇到下一个yield语句或函数结束。如果Generator函数执行到最后,没有遇到新的yield语句,那么迭代器对象的done属性会变为true,表示函数执行结束。


Generator函数的应用场景

惰性计算

惰性计算是指只在需要的时候才计算结果。Generator函数可以通过yield语句的使用,实现惰性计算的效果。在每次调用next方法时,可以根据需要计算并返回结果,而不是一次性计算所有结果。

例如,我们可以使用Generator函数来实现一个斐波那契数列的生成器:

function* fibonacci() {
  let a = 0;
  let b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3

在上面的代码中,fibonacci函数是一个Generator函数,通过yield语句返回斐波那契数列的每一项。每次调用next方法时,都会计算并返回下一项的值。

异步操作

Generator函数可以用于处理异步操作,通过yield语句的使用,可以使异步操作的代码看起来像同步操作一样。

例如,我们可以使用Generator函数来实现一个异步任务的执行器:

function* asyncTask() {
  const result1 = yield asyncOperation1();
  const result2 = yield asyncOperation2(result1);
  return result2;
}

function asyncOperation1() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('result1');
    }, 1000);
  });
}

function asyncOperation2(value) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`result2: ${value}`);
    }, 1000);
  });
}

const task = asyncTask();
task.next().value.then((result1) => {
  task.next(result1).value.then((result2) => {
    console.log(result2); // result2: result1
  });
});

在上面的代码中,asyncTask函数是一个Generator函数,通过yield语句暂停函数的执行,并等待异步操作的结果。每次调用next方法时,都会执行下一个异步操作,并将上一个异步操作的结果传递给下一个异步操作。

迭代器

Generator函数可以用来实现迭代器。通过yield语句的使用,可以方便地生成一个可迭代对象。

例如,我们可以使用Generator函数来实现一个简单的迭代器:

function* myIterator() {
  yield 1;
  yield 2;
  yield 3;
}

const iterator = myIterator();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3

在上面的代码中,myIterator函数是一个Generator函数,通过yield语句返回迭代器的每一项。每次调用next方法时,都会返回迭代器的下一项。


Generator函数与普通函数的区别

Generator函数与普通函数在语法上有一些区别:

  • Generator函数的定义在函数名前面有一个星号(*)。
  • Generator函数内部可以使用yield关键字来暂停函数的执行,并返回一个值。
  • Generator函数返回的是一个迭代器对象,而不是一个具体的值。

Generator函数的注意事项
在使用Generator函数时,需要注意以下几点:

  • Generator函数不能使用箭头函数的语法定义,只能使用function关键字定义。
  • Generator函数内部不能使用箭头函数,因为箭头函数没有自己的this和arguments,而Generator函数内部的yield语句需要依赖this和arguments。
  • Generator函数不能使用new关键字调用,因为Generator函数返回的是一个迭代器对象,而不是一个构造函数。

示例代码

下面是一个完整的示例代码,演示了Generator函数的基本用法和应用场景:

// 惰性计算
function* fibonacci() {
  let a = 0;
  let b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3

// 异步操作
function* asyncTask() {
  const result1 = yield asyncOperation1();
  const result2 = yield asyncOperation2(result1);
  return result2;
}

function asyncOperation1() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('result1');
    }, 1000);
  });
}

function asyncOperation2(value) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`result2: ${value}`);
    }, 1000);
  });
}

const task = asyncTask();
task.next().value.then((result1) => {
  task.next(result1).value.then((result2) => {
    console.log(result2); // result2: result1
  });
});

// 迭代器
function* myIterator() {
  yield 1;
  yield 2;
  yield 3;
}

const iterator = myIterator();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3

通过使用Generator函数,我们可以实现惰性计算、异步操作和迭代器等功能,使代码更加简洁和易于理解。同时,我们也需要注意Generator函数的语法和使用注意事项,以充分发挥其功能和优势。

在这里插入图片描述


  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Generator函数是一种特殊的函数,它是一个状态机,可以暂停执行并在需要时恢复执行。Generator函数的定义使用function关键字和一个星号(*),内部使用yield表达式来定义不同的内部状态。调用Generator函数后,函数并不会立即执行,而是返回一个指向内部状态的指针对象。通过调用这个指针对象的next()方法,可以逐步执行Generator函数内部的代码,并返回每个阶段的值和是否执行完毕的状态。 在Generator函数内部,可以使用yield*表达式来执行另一个Generator函数。yield*表达式可以将执行权交给另一个Generator函数,并在其执行完毕后再返回执行权给当前Generator函数Generator函数的数据交换可以通过调用next()方法传入参数来实现。在Generator函数内部,可以使用yield表达式来接收传入的参数,并返回相应的值。每次调用next()方法时,传入的参数会作为上一个阶段异步任务的返回结果,被函数体内的变量接收。 总结来说,Generator函数是一种特殊的函数,可以暂停执行并在需要时恢复执行。它通过yield表达式来定义不同的内部状态,并通过next()方法来逐步执行和控制函数的执行流程。yield*表达式可以在一个Generator函数内部执行另一个Generator函数。数据交换可以通过调用next()方法并传入参数来实现。 #### 引用[.reference_title] - *1* *3* [es6中的generator函数详解](https://blog.csdn.net/weixin_43638968/article/details/105475881)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Generator函数](https://blog.csdn.net/qq_43239667/article/details/123984997)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猫娃来啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值