
es-toolkit BigInt 降序生成rangeRight 用法、源码原理与边界行为全解析【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkites-toolkit 在es-toolkit/bigint子路径下提供了专门面向BigInt的数值工具集rangeRight便是其中用于按降序生成BigInt序列的函数。本文以官方文档 docs/ja/reference/bigint/rangeRight.md 为骨架结合 src/bigint/rangeRight.ts 源码与 src/bigint/rangeRight.spec.ts 测试完整讲解它的三种调用形式、与range的镜像关系、step边界规则以及底层实现原理帮助你安全处理超出Number.MAX_SAFE_INTEGER的降序区间枚举。函数签名与三种调用形式rangeRight与普通数值类型的rangeRight语义一致但输入输出全部使用BigInt因此可以精确表示任意大的整数区间。官方文档给出的类型签名如下const numbers rangeRight(end); const numbers rangeRight(start, end); const numbers rangeRight(start, end, step);从源码 src/bigint/rangeRight.ts 可以看出函数通过 TypeScript 重载声明了三种形态最终合并为一个实现export function rangeRight(start: bigint, end?: bigint, step 1n): bigint[] { if (end null) { end start; start 0n; } if (step 0n) { throw new Error(The step value must be a non-zero bigint.); } const length bigIntRangeLength(start, end, step); const result new Arraybigint(length); for (let i 0; i length; i) { result[i] start BigInt(length - i - 1) * step; } return result; }注意一个易被忽略的设计当只传入一个参数时该参数被当作end而start自动置为0n。这一点与range完全一致也解释了为什么rangeRight(4n)得到的是[3n, 2n, 1n, 0n]而非包含4n的序列。专属入口为什么只能从 es-toolkit/bigint 导入文档中特别注明该函数仅能从es-toolkit/bigint独家导入以避免与其他数值类型的同名函数产生潜在冲突。确实es-toolkit 在es-toolkit/compat中还提供了面向Number的rangeRight见 benchmarks/performance/rangeRight.bench.ts两者重名但类型不同。因此使用时请务必显式从子路径导入import { rangeRight } from es-toolkit/bigint;它由 src/bigint/index.ts 统一导出与range、clamp、inRange、sum等 BigInt 工具并列。使用一rangeRight(end) —— 从 end 前一位倒数到 0n当你希望从end的紧邻前一个值开始一路递减到0n含时使用单参数形式。文档示例import { rangeRight } from es-toolkit/bigint; console.log(rangeRight(4n)); // [3n, 2n, 1n, 0n] console.log(rangeRight(0n)); // []参数endbigint—— 范围的结束值不包含在结果中。返回值bigint[]—— 从end紧邻前一位递减到0n的BigInt数组。当end为0n时end紧邻前一位是-1n低于起点0n没有任何可生成的值因此返回空数组。测试 src/bigint/rangeRight.spec.ts 对rangeRight(4n) [3n, 2n, 1n, 0n]做了断言。使用二rangeRight(start, end) —— 倒数到任意起点当你的降序区间终点不是0n时传入两个参数指定区间。文档示例import { rangeRight } from es-toolkit/bigint; console.log(rangeRight(2n, 5n)); // [4n, 3n, 2n] console.log(rangeRight(-3n, 0n)); // [-1n, -2n, -3n]参数startbigint—— 范围的起始值包含在结果中作为序列的最后一个元素endbigint—— 范围的结束值不包含在结果中作为序列的第一个元素的前驱。返回值bigint[]—— 从end紧邻前一位递减到start含的数组。第二个例子直观体现了负数区间rangeRight(-3n, 0n)从0n之前即-1n开始递减到-3n结果为[-1n, -2n, -3n]。注意此时的start-3n小于end0n序列是递减方向这与数学直觉一致。使用三rangeRight(start, end, step) —— 自定义步长与镜像关系当你需要以1n以外的间隔枚举时使用三参数形式。官方文档特别强调了一个重要性质返回结果与相同参数调用range的结果完全相反import { range, rangeRight } from es-toolkit/bigint; console.log(rangeRight(0n, 10n, 2n)); // [8n, 6n, 4n, 2n, 0n] console.log(rangeRight(5n, 0n, -1n)); // [1n, 2n, 3n, 4n, 5n] // 始终是相同参数 range 的逆序 console.log(rangeRight(0n, 10n, 3n)); // [9n, 6n, 3n, 0n] console.log(range(0n, 10n, 3n)); // [0n, 3n, 6n, 9n]其中第二个例子展示了负步长的语义rangeRight(5n, 0n, -1n)等价于先求出升序此处实为降序的range(5n, 0n, -1n) [5n, 4n, 3n, 2n, 1n]再反转得到[1n, 2n, 3n, 4n, 5n]。也就是说rangeRight并不改变步长的“方向语义”它只是把range的产出整体反转——正步长对应降序输出负步长反而得到升序输出。参数startbigint—— 范围的起始值包含endbigint—— 范围的结束值不包含stepbigint可选—— 计数间隔默认1n。返回值bigint[]——range(start, end, step)的降序版本。步长背离 end 时返回空数组文档明确指出当步长指向远离结束值的方向时没有任何可生成的值返回空数组import { rangeRight } from es-toolkit/bigint; console.log(rangeRight(0n, 5n, -1n)); // []这里start 0n、end 5n步长-1n指向负方向而end在正方向步长背离结束值故结果为空。对应测试见 src/bigint/rangeRight.spec.ts。同理可推rangeRight(5n, 0n, 1n)也会得到[]。错误处理step 为 0n 时抛出异常由于步长为0n会导致死循环或歧义rangeRight与range一样会直接抛出错误import { rangeRight } from es-toolkit/bigint; rangeRight(0n, 5n, 0n); // Error: The step value must be a non-zero bigint.从 src/bigint/rangeRight.ts 可以看到该错误在参数归一化之后、长度计算之前被抛出错误信息为The step value must be a non-zero bigint.。测试 src/bigint/rangeRight.spec.ts 用toThrowError对该信息做了精确断言。源码级原理一次分配 等差数列填充相比逐项push的朴素实现rangeRight采用了“先算长度、预分配数组、再按等差公式填充”的策略这正是 es-toolkit 保持高性能的原因之一。关键步骤长度计算调用内部工具 src/_internal/bigIntRangeLength.ts它用纯BigInt算术实现Math.ceil((end - start) / step)的天花板除法export function bigIntRangeLength(start: bigint, end: bigint, step: bigint): number { const difference end - start; if (step 0n) { return difference 0n ? 0 : Number((difference step - 1n) / step); } return difference 0n ? 0 : Number((difference step 1n) / step); }正步长时若difference 0n直接返回 0即“步长背离 end”的情形负步长时若difference 0n返回 0。注释中也说明这与 Number 版实现Math.ceil((end - start) / step)语义完全对齐只是换成了无精度损失的 BigInt 运算。预分配new Arraybigint(length)一次性确定数组容量避免动态扩容。反向填充核心公式result[i] start BigInt(length - i - 1) * step直接按索引倒推位置无需先构造升序数组再reverse()既省一次遍历也省一份临时内存。对比 src/bigint/range.ts 中result[i] start BigInt(i) * step的正向填充两者共用bigIntRangeLength与同样的参数归一化逻辑结构高度对称。与 range 的关系及超越安全整数的价值rangeRight与 range 是一对“镜像”函数rangeRight(start, end, step)始终等于range(start, end, step).reverse()。测试 src/bigint/rangeRight.spec.ts 用toEqual(range(0n, 10n, 3n).reverse())固化了这个不变量。两者的共同价值在于BigInt 在任何大小下都保持精确因此可以安全构建超出Number.MAX_SAFE_INTEGER即9007199254740991的区间而不会出现数值悄悄碰撞。例如与 range 配合import { range } from es-toolkit/bigint; // Number 无法精确表示这些值BigInt 可以 console.log(range(9007199254740993n, 9007199254740996n)); // [9007199254740993n, 9007199254740994n, 9007199254740995n]同理rangeRight也能对这类超大区间做精确的降序枚举这在处理时间戳纳秒级、哈希值或任意精度业务 ID 的区间倒序场景中非常实用。性能基准仓库在 benchmarks/performance/rangeRight.bench.ts 中提供了rangeRight的基准测试使用 Vitest 的bench分别测量es-toolkit/rangeRight、es-toolkit/compat/rangeRight与lodash/rangeRight在rangeRight(0, 100, 1)场景下的耗时。需要说明的是该基准针对的是 Number 版rangeRight但它验证了 es-toolkit 在同类函数上的实现竞争力BigInt 版虽未被单独纳入该基准却共享了“预分配 等差数列填充”的同一套优化思路。总结调用形式示例结果rangeRight(end)rangeRight(4n)[3n, 2n, 1n, 0n]rangeRight(start, end)rangeRight(2n, 5n)[4n, 3n, 2n]rangeRight(start, end, step)rangeRight(0n, 10n, 2n)[8n, 6n, 4n, 2n, 0n]负步长rangeRight(5n, 0n, -1n)[1n, 2n, 3n, 4n, 5n]步长背离 endrangeRight(0n, 5n, -1n)[]step 0nrangeRight(0n, 5n, 0n)抛出Error使用要点回顾从es-toolkit/bigint导入避免与 Number 版同名函数混淆end永远不包含在结果中start始终包含结果恒等于相同参数range的逆序step默认1n不可为0n背离end时返回空数组底层由 bigIntRangeLength 计算长度后预分配数组通过等差公式一次填满兼顾正确性与性能。需要进一步了解正向枚举、区间判断或求和等 BigInt 工具可继续阅读 docs/ja/reference/bigint/range.md 及 src/bigint/index.ts 中导出的其余函数。【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考