es-toolkit 兼容层 subtract 函数深度解析:用法、源码原理与边界行为
es-toolkit 兼容层 subtract 函数深度解析用法、源码原理与边界行为【免费下载链接】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导读subtract是 es-toolkit 兼容层es-toolkit/compat中与 Lodash 保持 API 一致的减法工具函数用于计算两个数值之差并在任一入参为NaN时返回NaN。本文以 subtract 官方参考文档 为主线结合 subtract 源码、单元测试 及其底层 toNumber、toString 工具完整讲解其调用方式、参数约定、返回值语义、源码级实现原理与各类边界行为帮助你在 Lodash 迁移或日常编码中正确使用它。subtract 是什么subtract是 es-toolkit 兼容模块es-toolkit/compat提供的数学工具函数功能与 Lodash 的_.subtract完全一致从第一个数中减去第二个数。它的签名非常简洁const result subtract(value, other);在 es-toolkit 的模块体系中subtract归属于compatLodash 兼容层而非主入口。它通过 compat.ts 统一导出export { subtract } from ./math/subtract.ts;因此你可以从es-toolkit/compat直接引入使用详见下文使用方式。为什么官方建议优先使用-运算符原文档在开头就给出了一个醒目的警告subtract函数因为额外的函数调用而运行较慢请优先使用更快、更简单的-运算符。// 推荐直接用运算符 const result value - other; // 仅在需要 Lodash 兼容行为时使用 const result subtract(value, other);这个警告背后是实实在在的实现事实从 subtract.ts 可以看出一次subtract调用至少会经历参数判空、类型分支判断并视情况调用toString/toNumber再执行减法函数调用与类型转换的开销远高于一个原生的-运算符。因此日常数值相减直接用-运算符性能最好从 Lodash 迁移代码 / 需要保持兼容语义使用subtract让行为与 Lodash 完全对齐。使用方式导入import { subtract } from es-toolkit/compat;基本减法// 基本减法 subtract(6, 4); // Returns: 2 subtract(10, 3); // Returns: 7负数处理// 负数处理 subtract(-6, 4); // Returns: -10 subtract(6, -4); // Returns: 10NaN 处理// NaN 处理 subtract(NaN, 4); // Returns: NaN subtract(6, NaN); // Returns: NaN subtract(NaN, NaN); // Returns: NaN参数与返回值参数Parametersvalue(number)被减数minuend即相减运算中的第一个数other(number)减数subtrahend即要从第一个数中减去的数。返回值Returns(number)返回第二个数从第一个数中减去的结果若任一入参为NaN返回NaN。对应到源码 subtract.ts 中的 JSDoc 注释/** * Subtracts one number from another. * * If either of the numbers is NaN, the function returns NaN. * * param value The first number. (minuend) * param other The second number.(subtrahend) * returns The difference of the two numbers, or NaN if any input is NaN. */源码实现原理要真正用好subtract理解其底层实现是关键。完整实现如下src/compat/math/subtract.tsimport { toNumber } from ../util/toNumber.ts; import { toString } from ../util/toString.ts; export function subtract(value: number, other: number): number { if (value undefined other undefined) { return 0; } if (value undefined || other undefined) { return value ?? other; } if (typeof value string || typeof other string) { value toString(value) as any; other toString(other) as any; } else { value toNumber(value); other toNumber(other); } return value - other; }从源码结构可以梳理出四条核心逻辑分支1. 两个参数都缺失返回 0if (value undefined other undefined) { return 0; }当调用subtract()无任何参数时返回0。这一行为与 Lodash 保持一致在测试中也有明确断言subtract.spec.tsit(\subtract\ should return \0\ when no arguments are given, () { // ts-expect-error - invalid arguments expect(subtract()).toBe(0); });2. 仅提供一个参数返回该参数本身if (value undefined || other undefined) { return value ?? other; }当只传入一个参数时另一个为undefined直接返回已传入的那个值不做任何减法。测试覆盖了三种情况subtract.spec.tsit(\subtract\ should work with only one defined argument, () { expect(subtract(6)).toBe(6); // 只有被减数 expect(subtract(6, undefined)).toBe(6); // 减数为 undefined expect(subtract(undefined, 4)).toBe(4); // 只有减数 });3. 字符串参数的转换路径走 toStringif (typeof value string || typeof other string) { value toString(value) as any; other toString(other) as any; }只要任一参数是字符串两个参数都会先经过toString再相减。之所以单独为字符串开一条路径是为了与 Lodash 保持精确兼容数字字符串会被转为对应数值例如subtract(6, 4)得到2测试 subtract.spec.ts 特意注明了不强制将参数转为 number但字符串减法依然生效toString内部对数组、Symbol等类型有特殊处理见 toString.ts。4. 其余类型走 toNumber} else { value toNumber(value); other toNumber(other); } return value - other;非字符串参数统一交给toNumber转换。toNumber的核心实现toNumber.tsexport function toNumber(value: any): number { if (isSymbol(value)) { return NaN; } return Number(value); }它与原生Number()的关键区别在于遇到Symbol时返回NaN而非抛异常这是 Lodash 兼容语义的重要一环。边界行为与测试佐证subtract的边界行为非常丰富全部由 subtract.spec.ts 验证值得逐一说明。正数、负数、混合符号it(should return the difference of two positive numbers, () { expect(subtract(1, 5)).toBe(-4); expect(subtract(5, 1)).toBe(4); }); it(should return the difference when both numbers are negative, () { expect(subtract(-1, -5)).toBe(4); expect(subtract(-5, -1)).toBe(-4); }); it(should return the difference of a negative and a positive number, () { expect(subtract(-1, 5)).toBe(-6); expect(subtract(5, -1)).toBe(6); });NaN 传播it(should return NaN if the first value is NaN, () { expect(subtract(NaN, 10)).toBe(NaN); }); it(should return NaN if the second value is NaN, () { expect(subtract(10, NaN)).toBe(NaN); }); it(should return NaN if both values are NaN, () { expect(subtract(NaN, NaN)).toBe(NaN); });保留0的符号这是最刁钻的兼容行为之一当只传入一个参数时0与-0的符号必须被保留测试通过1 / result判断符号subtract.spec.tsit(\subtract\ should preserve the sign of \0\, () { const values [0, 0, -0, -0]; const expected [ [0, Infinity], [0, Infinity], [-0, -Infinity], [-0, -Infinity], ]; // subtract(0) 01 / 0 Infinity // subtract(-0) -01 / -0 -Infinity });对象与 Symbol 转为 NaN由于toNumber对Symbol返回NaN而普通对象经Number()转换也为NaN因此it(\subtract\ should convert objects to \NaN\, () { expect(subtract(0, {})).toEqual(NaN); expect(subtract({}, 0)).toEqual(NaN); }); it(\subtract\ should convert symbols to \NaN\, () { expect(subtract(0, symbol)).toEqual(NaN); expect(subtract(symbol, 0)).toEqual(NaN); });行为速查表调用形式结果依据subtract(6, 4)2基本减法subtract(-6, 4)-10负被减数subtract(6, -4)10负减数subtract(NaN, 4)/subtract(6, NaN)/subtract(NaN, NaN)NaNNaN 传播subtract()0双参数缺失subtract(6)/subtract(6, undefined)/subtract(undefined, 4)传入的那个值单参数subtract(6, 4)2字符串走toStringsubtract(0, {})/subtract({}, 0)NaN对象转 NaNsubtract(0, symbol)/subtract(symbol, 0)NaNSymbol 转 NaNsubtract(-0)-0保留符号零符号保留在项目中的定位与适用场景在 es-toolkit 中subtract属于compatLodash 兼容层的 math 模块与 add、multiply、divide 等四则运算工具并列。它面向的核心场景是Lodash 迁移将使用_.subtract的存量代码无缝迁移到 es-toolkit无需修改调用方式保持兼容语义需要NaN传播、缺参返回、类型转换等与 Lodash 完全一致的行为时用subtract保证行为对齐回调/高阶函数场景在reduce、map等需要传入函数的地方subtract可以作为一等函数直接传递例如累减而-运算符无法作为值传递。如果只是普通代码中的两个数字相减请遵循官方文档的警告直接使用-运算符以获得最佳性能。总结subtract是 es-toolkit 兼容层中一个 API 极简但语义丰富的数学工具核心行为subtract(value, other)返回两数之差任一入参为NaN时返回NaN实现原理缺参返回0或单参原样返回字符串参数走toString其余走toNumberSymbol 转为NaN后再相减src/compat/math/subtract.ts边界行为覆盖正负混合、NaN 传播、零符号保留、对象/Symbol 转 NaN 等场景全部有测试断言佐证src/compat/math/subtract.spec.ts性能提示由于函数调用与类型转换开销官方明确建议能用-运算符的地方直接使用运算符subtract专为 Lodash 兼容场景设计。如需深入探索其他兼容函数或整体架构可继续阅读 docs/compat/intro.md 与 compat.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),仅供参考