”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 了解 JavaScript 生成器:强大的代码流控制工具

了解 JavaScript 生成器:强大的代码流控制工具

发布于2024-11-08
浏览:399

Razumevanje JavaScript Generatora: Moćan Alat za Kontrolu Toka Koda

生成器是 JavaScript 中最强大的功能之一,它允许我们编写可以根据需要暂停和恢复的代码。与一次执行所有代码的常规函数​​不同,生成器使用延迟执行,增量返回值,从而更容易处理数据序列、迭代或长时间运行的进程。

发电机如何工作?

在JavaScript中,生成器是使用function*关键字定义的,并与yield关键字结合,允许部分执行函数。每次我们调用生成器函数时,它不会立即执行,而是返回一个允许受控执行的迭代器。

例子:

const id = (function* () {
    let i = 1;
    while (true) {
        yield i;
        i  = 1;
    }
})();

在此示例中,函数生成器返回无限的数字序列,其中每个数字仅在需要时生成并返回。

yield 有什么作用?

yield 关键字停止生成器的执行并将值返回给外界。在下一个函数调用(使用 next())时,生成器从上次停止的地方继续。

调用生成器是什么样的:

console.log(id.next().value); // 1
console.log(id.next().value); // 2
console.log(id.next().value); // 3

每次调用 next() 都会返回数组的下一个值,并在下一个yield 时暂停函数。

发电机的优点

  • 懒惰:
    生成器不会立即执行所有内容,而是仅在需要时才生成值。这非常适合处理无限序列或大型数据数组。

  • 流量控制:
    暂停和恢复功能的可能性可以更好地控制长时间运行的进程。

  • 效率:
    生成器不是将所有值存储在内存中,而是一次返回一个,这减少了内存消耗。

发电机的缺点

虽然生成器很有用,但它们有几个潜在的问题:

  • 复杂流控制:
    暂停和恢复会使代码更难理解和调试,尤其是在复杂的场景中。

  • 表现:
    在某些情况下,暂停和恢复代码可能会带来额外的开销,从而降低效率。

  • 有限的:
    每次调用返回一个值,如果需要一次访问大量数据,这可能会效率低下。

  • 兼容性:
    生成器是 ECMAScript 2015 (ES6) 标准的一部分,因此如果没有像 Babel 这样的附加工具,较旧的浏览器可能不支持它们。

替代方法

如果生成器引入太多复杂性,您可以考虑替代方案:

带回调的递归函数:

function generateID(callback, start = 1) {
    callback(start);
    setTimeout(() => generateID(callback, start   1), 0);
}
  • 优点:
    更容易的流程控制:虽然使用了递归,但在控制程序流程方面,函数的可读性和清晰性更高。
    异步执行:使用setTimeout可以实现异步操作,这有助于保持性能。

  • 缺点:
    递归开销:对于非常大量的迭代,可能会出现递归问题(堆栈溢出)。

循环:
对于较小的数组,生成预定数量的值的简单循环可能是更有效的选择。

function generateIDs(limit) {
    const ids = [];
    for (let i = 1; i 



  • 优点:
    实现简单:该方案简单易懂,且没有流控问题。
    快速生成:一次性生成所有值,可以以更少的迭代次数提高效率。

  • 缺点:
    内存消耗:所有值都存储在内存中,这对于大型数组可能会出现问题。
    不偷懒:所有 ID 都是预先生成的,如果您不需要全部 ID,效率可能会很低。

迭代器:
通过 .next() 方法返回可迭代值的对象,类似于生成器,但具有更多控制权。

function createIDIterator() {
    let i = 1;
    return {
        next() {
            return { value: i  , done: false };
        }
    };
}

const idIterator = createIDIterator();

console.log(idIterator.next().value); // 1
console.log(idIterator.next().value); // 2
console.log(idIterator.next().value); // 3
  • 优点:
    流程控制:与生成器具有类似的功能,但执行更加线性。
    更简单的代码:没有收益,这可以使代码更容易理解。

  • 缺点:
    没有自动暂停:您必须手动管理迭代,这在某些情况下可能会很不方便。

使用 async/await 异步生成
如果 ID 是异步生成的,则可以将 async/await 与返回 Promise 的函数一起使用。

async function generateID(start = 1) {
    let i = start;
    while (true) {
        await new Promise((resolve) => setTimeout(resolve, 0));
        console.log(i  );
    }
}

generateID(); 
  • 优点:
    异步执行:高效处理长时间运行的操作,而不阻塞主执行流程。
    现代语法:async/await 是一种更现代、更直观的异步代码处理方式。

  • 缺点:
    不适合同步代码:如果需要同步生成,这个解决方案并不理想。

结论

生成器是处理大量无限数据数组以及需要暂停和恢复进程的应用程序中的流量控制的绝佳工具。然而,它们的复杂性和潜在的性能问题意味着它们应该谨慎使用。根据应用程序的要求,迭代、递归或异步代码等替代解决方案可能更合适。

版本声明 本文转载于:https://dev.to/jelena_petkovic/razumevanje-javascript-generatora-mocan-alat-za-kontrolu-toka-koda-2hpo?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 为什么我的CSS背景图像出现?
    为什么我的CSS背景图像出现?
    故障排除:CSS背景图像未出现 ,您的背景图像尽管遵循教程说明,但您的背景图像仍未加载。图像和样式表位于相同的目录中,但背景仍然是空白的白色帆布。而不是不弃用的,您已经使用了CSS样式: bockent {背景:封闭图像文件名:背景图:url(nickcage.jpg); 如果您的html,css...
    编程 发布于2025-04-29
  • 您如何在Laravel Blade模板中定义变量?
    您如何在Laravel Blade模板中定义变量?
    在Laravel Blade模板中使用Elegance 在blade模板中如何分配变量对于存储以后使用的数据至关重要。在使用“ {{}}”分配变量的同时,它可能并不总是最优雅的解决方案。幸运的是,Blade通过@php Directive提供了更优雅的方法: $ old_section =“...
    编程 发布于2025-04-29
  • 在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在C中的显式删除 在C中的动态内存分配时,开发人员通常会想知道是否有必要在heap-procal extrable exit exit上进行手动调用“ delete”操作员,但开发人员通常会想知道是否需要手动调用“ delete”操作员。本文深入研究了这个主题。 在C主函数中,使用了动态分配变量(H...
    编程 发布于2025-04-29
  • 如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    postgresql:为每个唯一标识符在postgresql中提取最后一行,您可能需要遇到与数据集合中每个不同标识的信息相关的信息。考虑以下数据:[ 1 2014-02-01 kjkj 在数据集中的每个唯一ID中检索最后一行的信息,您可以在操作员上使用Postgres的有效效率: id dat...
    编程 发布于2025-04-29
  • Python中嵌套函数与闭包的区别是什么
    Python中嵌套函数与闭包的区别是什么
    嵌套函数与python 在python中的嵌套函数不被考虑闭合,因为它们不符合以下要求:不访问局部范围scliables to incling scliables在封装范围外执行范围的局部范围。 make_printer(msg): DEF打印机(): 打印(味精) ...
    编程 发布于2025-04-29
  • 哪种方法更有效地用于点 - 填点检测:射线跟踪或matplotlib \的路径contains_points?
    哪种方法更有效地用于点 - 填点检测:射线跟踪或matplotlib \的路径contains_points?
    在Python Matplotlib's path.contains_points FunctionMatplotlib's path.contains_points function employs a path object to represent the polygon.它...
    编程 发布于2025-04-29
  • 如何在JavaScript对象中动态设置键?
    如何在JavaScript对象中动态设置键?
    在尝试为JavaScript对象创建动态键时,如何使用此Syntax jsObj['key' i] = 'example' 1;不工作。正确的方法采用方括号: jsobj ['key''i] ='example'1; 在JavaScript中,数组是一...
    编程 发布于2025-04-29
  • 如何使用替换指令在GO MOD中解析模块路径差异?
    如何使用替换指令在GO MOD中解析模块路径差异?
    在使用GO MOD时,在GO MOD 中克服模块路径差异时,可能会遇到冲突,其中3个Party Package将另一个PAXPANCE带有导入式套件之间的另一个软件包,并在导入式套件之间导入另一个软件包。如回声消息所证明的那样: go.etcd.io/bbolt [&&&&&&&&&&&&&&&&...
    编程 发布于2025-04-29
  • 哪种在JavaScript中声明多个变量的方法更可维护?
    哪种在JavaScript中声明多个变量的方法更可维护?
    在JavaScript中声明多个变量:探索两个方法在JavaScript中,开发人员经常遇到需要声明多个变量的需要。对此的两种常见方法是:在单独的行上声明每个变量: 当涉及性能时,这两种方法本质上都是等效的。但是,可维护性可能会有所不同。 第一个方法被认为更易于维护。每个声明都是其自己的语句,使其...
    编程 发布于2025-04-29
  • 如何在其容器中为DIV创建平滑的左右CSS动画?
    如何在其容器中为DIV创建平滑的左右CSS动画?
    通用CSS动画,用于左右运动 ,我们将探索创建一个通用的CSS动画,以向左和右移动DIV,从而到达其容器的边缘。该动画可以应用于具有绝对定位的任何div,无论其未知长度如何。问题:使用左直接导致瞬时消失 更加流畅的解决方案:混合转换和左 [并实现平稳的,线性的运动,我们介绍了线性的转换。这...
    编程 发布于2025-04-29
  • 如何限制动态大小的父元素中元素的滚动范围?
    如何限制动态大小的父元素中元素的滚动范围?
    在交互式接口中实现垂直滚动元素的CSS高度限制问题:考虑一个布局,其中我们具有与用户垂直滚动一起移动的可滚动地图div,同时与固定的固定sidebar保持一致。但是,地图的滚动无限期扩展,超过了视口的高度,阻止用户访问页面页脚。$("#map").css({ marginT...
    编程 发布于2025-04-29
  • 在Java中如何为PNG文件添加坐标轴和标签?
    在Java中如何为PNG文件添加坐标轴和标签?
    如何用java 在现有png映像中添加轴和标签的axes和labels如何注释png文件可能具有挑战性。与其尝试可能导致错误和不一致的修改,不如建议在图表创建过程中集成注释。使用JFReechArt import java.awt.color; 导入java.awt.eventqueue; 导入...
    编程 发布于2025-04-29
  • 解决MySQL插入Emoji时出现的\\"字符串值错误\\"异常
    解决MySQL插入Emoji时出现的\\"字符串值错误\\"异常
    Resolving Incorrect String Value Exception When Inserting EmojiWhen attempting to insert a string containing emoji characters into a MySQL database us...
    编程 发布于2025-04-29
  • 在GO中构造SQL查询时,如何安全地加入文本和值?
    在GO中构造SQL查询时,如何安全地加入文本和值?
    在go中构造文本sql查询时,在go sql queries 中,在使用conting and contement和contement consem per时,尤其是在使用integer per当per当per时,per per per当per. [&​​&&&&&&&&&&&&&&&默元组方法在...
    编程 发布于2025-04-29
  • Go web应用何时关闭数据库连接?
    Go web应用何时关闭数据库连接?
    在GO Web Applications中管理数据库连接很少,考虑以下简化的web应用程序代码:出现的问题:何时应在DB连接上调用Close()方法?,该特定方案将自动关闭程序时,该程序将在EXITS EXITS EXITS出现时自动关闭。但是,其他考虑因素可能保证手动处理。选项1:隐式关闭终止数...
    编程 发布于2025-04-29

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3