资讯动态

es-toolkit 的 BigInt 版 range 函数:从入门到源码级解析

发布时间:2026/9/16 17:29:32 来源:尧图企业网站定制
es-toolkit 的 BigInt 版 range 函数从入门到源码级解析【免费下载链接】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类型的range函数用于生成从起始值含到终止值不含之间的BigInt数组。与Number版本不同BigInt版range不受Number.MAX_SAFE_INTEGER精度限制可以安全地构造超大范围。阅读本文后你将掌握range的三种调用形式、参数约定、边界行为与异常规则并通过源码与测试用例理解其底层实现原理。函数签名与基本约定range支持三种重载形式核心语义是从start含数到end不含const numbers range(end); const numbers range(start, end); const numbers range(start, end, step);单参数形式从0n开始计数双参数形式从指定的start开始计数三参数形式额外指定步长step默认1n可为负数实现降序。该函数仅在es-toolkit/bigint子路径下提供以避免与Number、其他数值类型下同名的类似函数产生潜在冲突。对应的实现文件为 src/bigint/range.ts并在 src/bigint/index.ts 中与其他BigInt工具clamp、inRange、max、median、percentile、sum等一同导出。使用方式详解形式一range(end)—— 从0n数到end之前当只需从0n开始计数时使用单参数形式import { range } from es-toolkit/bigint; console.log(range(4n)); // [0n, 1n, 2n, 3n] console.log(range(0n)); // []参数endbigint范围的终止值不包含在结果中。返回值bigint[]从0n到end之前的所有BigInt数组。形式二range(start, end)—— 从任意起始值开始当需要从非0n的起始值开始计数时使用双参数形式import { range } from es-toolkit/bigint; console.log(range(2n, 5n)); // [2n, 3n, 4n] console.log(range(-3n, 0n)); // [-3n, -2n, -1n] // 起始值与终止值相同时没有可数的值 console.log(range(3n, 3n)); // []参数startbigint范围的起始值包含在结果中。参数endbigint范围的终止值不包含在结果中。返回值bigint[]从start到end之前的BigInt数组。由于BigInt在任意大小下都保持精确你可以构造跨越Number.MAX_SAFE_INTEGER即9007199254740991的范围而不会像Number那样发生值的静默碰撞import { range } from es-toolkit/bigint; console.log(range(9007199254740993n, 9007199254740996n)); // [9007199254740993n, 9007199254740994n, 9007199254740995n]这一能力在需要处理大整数 ID、哈希区间或高精度序列场景时尤为实用。形式三range(start, end, step)—— 自定义步长与降序当需要以1n以外的间隔计数时使用三参数形式step为负数时则降序计数import { range } from es-toolkit/bigint; console.log(range(0n, 10n, 2n)); // [0n, 2n, 4n, 6n, 8n] console.log(range(5n, 0n, -1n)); // [5n, 4n, 3n, 2n, 1n] console.log(range(5n, 0n, -2n)); // [5n, 3n, 1n]如果step指向远离end的方向即正步长但start end或负步长但start end则没有任何可生成的值直接返回空数组import { range } from es-toolkit/bigint; console.log(range(0n, 5n, -1n)); // [] console.log(range(5n, 0n, 1n)); // []参数startbigint范围的起始值包含在结果中。参数endbigint范围的终止值不包含在结果中。参数stepbigint可选计数间隔默认值为1n。返回值bigint[]按step间隔从start数到end之前的BigInt数组。异常规则当step为0n时函数会抛出错误详见下文源码分析。源码级实现原理查看 src/bigint/range.ts 的实现可以发现range的核心流程分为三步参数归一化、长度预计算、循环填充。export function range(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(i) * step; } return result; }1. 参数归一化当只传入一个参数时end null实现将end赋值为传入值并把start置为0n从而统一走同一套内部逻辑。这与Number版本的 src/math/range.ts 中if (end null) { end start; start 0; }的处理方式完全一致。2. 零步长校验step 0n时直接抛出Error(The step value must be a non-zero bigint.)。注意这里只校验是否为0n负步长是被允许的用于降序计数。Number版本则额外要求step必须是整数Number.isInteger(step)且非零因为BigInt本身不存在小数概念所以无需该检查。3. 基于长度的预分配与填充range并没有采用边推边判断的逐项循环而是先用内部工具函数bigIntRangeLength计算出结果数组的长度再通过new Arraybigint(length)预分配数组随后用result[i] start BigInt(i) * step逐项填充。这种先算长度、再按索引写入的做法避免了数组反复扩容同时保证了大范围场景下的性能表现。长度计算函数位于 src/_internal/bigIntRangeLength.tsexport 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); }该函数本质上是Number版Math.ceil((end - start) / step)的BigInt实现通过(difference step - 1n) / step正步长与(difference step 1n) / step负步长完成BigInt上的向上取整除法。同时它统一处理了两类边界情况当step指向远离end的方向正步长下difference 0n或负步长下difference 0n时返回0对应文档中的空数组行为当start end时difference 0n正负步长路径都会返回0因此range(3n, 3n)的结果是[]。4. 与rangeRight的关联es-toolkit/bigint还提供了按降序输出的 src/bigint/rangeRight.ts。它复用了完全相同的bigIntRangeLength长度计算与step 0n校验逻辑唯一的区别在于填充方式result[i] start BigInt(length - i - 1) * step即从最后一个元素开始反向填充从而在结果顺序上实现倒序。也就是说range与rangeRight生成的是同一组元素、不同排列顺序两者共享同一套边界与异常语义。测试用例对行为的验证src/bigint/range.spec.ts 使用 Vitest 对上述全部行为做了覆盖验证可以作为理解函数契约的权威参考单参数从0n计数range(4n)等于[0n, 1n, 2n, 3n]双参数从指定值计数range(2n, 5n)等于[2n, 3n, 4n]自定义步长range(0n, 10n, 2n)等于[0n, 2n, 4n, 6n, 8n]range(0n, 5n, 2n)等于[0n, 2n, 4n]验证最后一个元素不会越过end负步长降序range(5n, 0n, -1n)等于[5n, 4n, 3n, 2n, 1n]range(5n, 0n, -2n)等于[5n, 3n, 1n]步长方向远离终点时返回空数组range(0n, 5n, -1n)与range(5n, 0n, 1n)均等于[]start end返回空数组range(3n, 3n)等于[]支持负区间range(-3n, 0n)等于[-3n, -2n, -1n]超越Number.MAX_SAFE_INTEGER依然精确range(9007199254740993n, 9007199254740996n)精确返回三个连续的BigIntstep为0n时抛出异常range(0n, 5n, 0n)抛出The step value must be a non-zero bigint.。与Number版range的对比与选型建议es-toolkit同时提供Number版rangesrc/math/range.ts从主入口es-toolkit导入。两者的核心差异体现在三方面维度Number版rangeBigInt版range导入路径es-toolkites-toolkit/bigint元素类型number[]bigint[]精度上限受Number.MAX_SAFE_INTEGER限制超出后可能静默碰撞任意大小保持精确步长校验要求非零整数仅要求非零BigInt无小数长度计算Math.ceil((end - start) / step)bigIntRangeLength的BigInt向上取整除法在普通业务数据索引、分页、常规计数场景下Number版range已足够而当范围涉及大整数如雪花 ID 区间、超大序列号、需要跨Number.MAX_SAFE_INTEGER的区间枚举时应选用es-toolkit/bigint的BigInt版range以确保每个值都精确无碰撞。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价