博客 / 詳情

返回

Lodash 加減乘除 add、subtract、multiply、divide方法源碼解讀

我們先看下Lodash中文文檔對add方法的解釋:

_.add(augend, addend)
兩個數相加。
參數
augend (number): 相加的第一個數。
addend (number): 相加的第二個數。
返回
(number): 返回總和。
例子

_.add(6, 4);
// => 10

接下來 我們通過源碼層次來看看add方法的具體用法

const add = createMathOperation((augend, addend) => augend + addend, 0)

export default add

從源碼層次可以看出 add方法是createMathOperation方法返回的函數,createMathOperation方法傳入兩個參數:
第一個參數是一個普通的add邏輯方法
第二個參數是一個默認值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 subtract

multiply方法

 * multiply(6, 4)
 * // => 24
 */
const multiply = createMathOperation((multiplier, multiplicand) => multiplier * multiplicand, 1)

export default multiply

divide方法

 * divide(6, 4)
 * // => 1.5
 */
const divide = createMathOperation((dividend, divisor) => dividend / divisor, 1)

export default divide
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.