)
教程文档【免费下载链接】30-seconds-of-codeCoding articles to level up your development skills项目地址https://gitcode.com/gh_mirrors/30/30-seconds-of-code点击查看免费下载ES6 生成器generator允许你定义可以暂停、退出、之后重新进入的函数并在暂停期间保留其上下文变量绑定。本篇文章以 30-seconds-of-code 仓库中的 range-generator 示例 为骨架从零实现一个生成 0..n 数值序列的范围生成器并逐步扩展出支持start、end、step三个参数的完整版本。读完本文你将掌握function*、yield的基本用法以及next()、for...of、展开运算符三种消费生成器输出的方式并能在实际项目中按需改造出日期范围生成器、条件生成器等多种变体。生成器的核心概念生成器函数用function*定义function关键字后跟一个星号通过yield表达式产出结果。与普通函数一次性执行完毕不同生成器函数在执行到yield时会暂停把当前的值返回给调用方调用方再次请求下一个值时生成器会从暂停处继续执行。这种可暂停、可重入、保留上下文的执行模型使生成器天然适合表达按需计算的序列。在 30-seconds-of-code 仓库中生成器相关技巧被集中组织在 generators 集合 下与range-generator并列的还有日期范围生成器、子串生成器、对象深度遍历生成器等多个实战示例本文末尾会给出这些衍生阅读路径。一个简单的范围生成器生成器的控制流初看比较绕因此先从最简实现开始只接收一个end值序列从0开始、步长为1。做法是使用for循环在每次迭代时yield当前下标iconst range function* (end) { for (let i 0; i end; i) yield i; }; for (let i of range(5)) console.log(i); // Logs: 0, 1, 2, 3, 4调用生成器函数并不会执行函数体而是返回一个生成器对象。上面的for...of循环会不断从生成器对象中取下一个值直到序列结束done: true。消费生成器的输出生成器的输出既可以按需逐步消费也可以一次性全部取完JavaScript 提供了三种常见方式。按需消费调用 next()生成器对象暴露了Generator.prototype.next()方法每次调用会返回一个形如{ value, done }的对象value是本次产出的值done为布尔值表示序列是否已结束。我们可以手动循环调用next()直到它返回{ value: undefined, done: true }const gen5 range(5); let x gen5.next(); while (!x.done) { console.log(x.value); x gen5.next(); } // Logs: 0, 1, 2, 3, 4这种消费方式的好处是惰性值只有在被请求时才计算特别适合处理大规模序列或无限序列。迭代输出for...of如前面的例子所示for...of可以直接迭代生成器的输出。这是因为生成器对象本身就是可迭代对象内部实现了Symbol.iterator协议for (let i of range(5)) console.log(i); // Logs: 0, 1, 2, 3, 4for...of在语法层面自动完成了取下一个值、检查done、交给循环体的整套流程是最简洁的迭代方式。一次性转为数组展开运算符最后一种方式是用展开运算符...一次性消费全部输出。当你需要把生成器结果转换成数组时这一招尤其好用30-seconds-of-code 为此专门整理了 generator-to-array 技巧console.log([...range(5)]); // Logs: [0, 1, 2, 3, 4]generator-to-array 一文还指出Set、Map的entries()等方法返回的正是生成器对象不能直接当数组用因此展开转数组是日常开发中的高频操作const generatorToArray gen [...gen]; const s new Set([1, 2, 1, 3, 1, 4]); generatorToArray(s.entries()); // [[ 1, 1 ], [ 2, 2 ], [ 3, 3 ], [ 4, 4 ]]添加 start 与 step 参数基础版本实现后可以把它扩展为接收start和step参数的完整版本让范围可以从指定值开始、按指定步长递增。为了让行为与 Python 的range()函数保持一致需要处理以下三种参数场景只传一个参数视为endstart默认0、step默认1传两个参数视为start和endstep默认1传三个参数依次为start、end、step。实现时利用end undefined判断只传了一个参数的情况并交换赋值const range function* (start, end, step 1) { if (end undefined) (end start), (start 0); for (let i start; i end; i step) yield i; }; [...range(4)]; // [0, 1, 2, 3] (scenario 1) [...range(6, 10)]; // [6, 7, 8, 9] (scenario 2) [...range(2, 10, 2)]; // [2, 4, 6, 8] (scenario 3)三个场景对应三条使用样例可以直接复制到浏览器控制台或 Node.js 中验证输出。生成器的边界情况与深入变体掌握了范围生成器的基础写法后可以从以下几个方向继续深入它们都以function*yield为共同核心围绕同一套暂停/重入机制展开。内存友好的惰性序列范围生成器的最大价值在于惰性求值序列元素不会一次性全部驻留内存而是在迭代时才逐个产生。仓库中的 initialize-array-with-generated-sequence 专门讨论了这一点指出当不需要一次性生成整个数组时用生成器做惰性初始化可以避免时间和内存的浪费其generateArrayWhile变体甚至可以根据条件动态决定序列何时结束const generateArrayWhile function* (conditionFn, mapFn) { let i 0; let el mapFn(i, undefined); while (conditionFn(i, el)) { yield el; i; el mapFn(i, el); } }; const range5 generateArrayWhile(i i 5, i i); [...range5]; // [0, 1, 2, 3, 4]无限序列重复值与条件生成生成器同样适合表达无限序列因为消费者可以随时停止取用。仓库中的 generate-values-repeatedly 用非终止的while (true)循环实现重复单个值或循环遍历数组的生成器generate-while 则把终止条件抽象成一个谓词函数predicate只要条件满足就持续产出新值非常适合表达生成到某个阈值为止的需求const generateWhile function* (seed, predicate, next) { let val seed; let nextSeed null; while (predicate(val)) { nextSeed yield val; val next(val, nextSeed); } return val; }; [...generateWhile(1, v v 5, v v)]; // [1, 2, 3, 4, 5]注意这里的yield表达式的返回值即传入next()的参数可以被接收并用于更新下一次产出的值——这正是生成器双向通信能力的体现。把生成器思想迁移到其他数据类型范围生成器的写法可以非常自然地迁移到其他数据类型日期范围date-range-generator 用同样的for循环结构配合Date.prototype.getDate()/setDate()逐日递增产出指定日期区间内的所有日期且文档明确建议读者先读 range-generator 建立生成器基础const dateRange function* (start, end, step 1) { for ( let d new Date(start); d new Date(end); d.setDate(d.getDate() step) ) yield new Date(d); }; [...dateRange(2021-06-01,2021-06-04)]; // [ 2021-06-01, 2021-06-02, 2021-06-03 ]子串枚举substring-generator 通过String.prototype.slice()配合for...in产出字符串的所有前缀/后缀子串对象遍历walk-through-object 用yield*递归委托给生成器自身实现对象的深度优先遍历自定义可迭代对象make-iterable 直接在对象上实现Symbol.iterator生成器方法让任意值变得可迭代。上述全部内容在仓库中的入口均为 generators 集合该集合还收录了enum、split-array-into-chunks、object-array-proxy等更多生成器应用场景可作为进一步学习的索引。小结本文从 30-seconds-of-code 的 range-generator 示例 出发完整走过了范围生成器的演进路径先用for循环 yield实现最简版本再介绍next()、for...of、展开运算符三种消费方式最后通过参数默认值与end undefined判断扩展出兼容 Pythonrange()语义的完整版本。围绕这套核心写法仓库中还沉淀了日期范围、条件生成、无限重复、惰性数组初始化等一系列同源变体读者可以在 generators 集合 中按需取用。赞分享教程文档【免费下载链接】30-seconds-of-codeCoding articles to level up your development skills项目地址https://gitcode.com/gh_mirrors/30/30-seconds-of-code点击查看免费下载相关推荐30-seconds-of-code用 ES6 生成器实现 JavaScript 日期范围生成器dateRange30 seconds of code用 ES6 生成器实现 JavaScript 日期范围生成器dateRange 导读 在处理日程、图表、日历等任何与时教程文档ES6 Generator生成器函数同步写法实现异步操作的技巧ES6 Generator生成器函数同步写法实现异步操作的技巧 ES6 Generator生成器函数是JavaScript异步编程的革命性特性它让你用同步的教程前端MudBlazor数值范围Range类与双滑块实现MudBlazor数值范围Range类与双滑块实现 引言解决数值范围选择的痛点 在Web应用开发中你是否经常遇到需要用户选择数值范围的场景比如价格区间筛前端UI组件设计系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考