本文深入解析Lodash中add、subtract、multiply和divide四个数学方法的源码实现。核心在于createMathOperation工厂函数,它统一处理参数校验、类型转换(baseToString与baseToNumber)及异常值处理。通过剖析源码,揭示Lodash如何保证数值计算的健壮性与一致性,适用于前端开发中需要精确数学运算的场景。
Lodash中文文档
首先参考Lodash官方文档对add方法的定义说明。
_.add(augend, addend)用于执行两个数字的加法运算。 参数augend (number): 表示被加数。 addend (number): 表示加数。 返回(number): 返回计算后的总和结果。
示例部分
_.add(6, 4);
// => 10add方法的具体使用场景演示
随后,我们将深入源码层面,剖析add方法的具体执行逻辑。
const add = createMathOperation((augend, addend) => augend + addend, 0)
export default add从源码结构分析可知,add方法实际上是createMathOperation方法返回的一个函数实例。该工厂方法接收两个关键参数:
第一个参数是一个执行基础加法逻辑的函数。
第二个参数指定了默认返回值,此处为0。
function createMathOperation(operator, defaultValue) {
//返回一个函数 value,other是调用lodash方法(例如_add)传入的参数
return (value, other) => {
//如果第一个参数和第二个参数都没有定义 则返回默认值0
if (value === undefined && other === undefined) {
return defaultValue
}
//如果第一个参数有值 第二个参数没有值 则返回第一个参数
if (value !== undefined && other === undefined) {
return value
}
//如果第一个参数没有值 第二个参数有值 则返回第二个参数
if (other !== undefined && value === undefined) {
return other
}
//如果第一个参数或者第二个参数为字符串(至少其中一个为字符串) 则将参数通过baseToString方法都转换为字符串
if (typeof value === 'string' || typeof other === 'string') {
value = baseToString(value)
other = baseToString(other)
}
else {
//如果两个参数都不是字符串 则将参数通过baseToNumber方法都转换为数字
value = baseToNumber(value)
other = baseToNumber(other)
}
//这个时候将被转换的参数传入createMathOperation方法的第一个操作函数,并返回结果
return operator(value, other)
}
}源码中涉及的baseToString工具函数
function baseToString(value) {
// 如果是字符串 直接返回
if (typeof value === 'string') {
return value
}
// 如果是数组 递归转换值(易受调用堆栈限制的影响)
if (Array.isArray(value)) {
return `${value.map(baseToString)}`
}
//如果是Symbol值 调用 Symbol.prototype.toString.call方法进行转换 例如:Symbol('a') 的转换结果为 'Symbol(a)'
if (isSymbol(value)) {
return symbolToString ? symbolToString.call(value) : ''
}
//对字符串0 返回0 或者'-0'的处理 这块我还没有想到什么应用场景 欢迎补充
const result = `${value}`
return (result === '0' && (1 / value) === -INFINITY) ? '-0' : result
}源码中涉及的baseToNumber工具函数
function baseToNumber(value) {
//如果是数字 直接返回
if (typeof value === 'number') {
return value
}
//如果是Symbol类型 返回NAN
if (isSymbol(value)) {
return NAN
}
//将字符串通过+转换为数字
return +value
}在baseToString和baseToNumber内部,调用了isSymbol方法以判断值类型。
function isSymbol(value) {
const type = typeof value
return type == 'symbol' || (type === 'object' && value != null && getTag(value) == '[object Symbol]')
}源码逻辑深度解析
通过对源码的追踪发现
——add() // 0 没有传参数直接返回默认值0
_add(true) // true 只有第一个参数 返回
_add(undefined,'5') // '5' 只有第二个参数直接返回
_add(3,5) //返回 8
_add('3',5) // 返回 '35'
_add('3',['5',4]) //返回 '35,4' 数组相加先调Array.prototype.toString方法 ['5',4]转为'5,4'
_add('3',Symbol('a')) //返回 '3Symbol(a)'Lodash库中的subtract(减法)、multiply(乘法)以及divide(除法)方法,均复用了createMathOperation这一核心实现机制。
subtract减法方法实现
* subtract(6, 4)
* // => 2
*/
const subtract = createMathOperation((minuend, subtrahend) => minuend - subtrahend, 0)
export default subtractmultiply乘法方法实现
* multiply(6, 4)
* // => 24
*/
const multiply = createMathOperation((multiplier, multiplicand) => multiplier * multiplicand, 1)
export default multiplydivide除法方法实现
* divide(6, 4)
* // => 1.5
*/
const divide = createMathOperation((dividend, divisor) => dividend / divisor, 1)
export default divide以上即为Lodash中add、subtract、multiply及divide四个数学方法的源码实现详解,更多Lodash相关技术文章欢迎持续关注本站后续更新。