深入浅出lodash之Math
发布于 6 年前 作者 sunfeng90 4044 次浏览 来自 分享

一、lodash版本:4.17.5 二、函数

1、add 1)含义:两个月相加

  1. 例子。

    const _ = require('lodash’);
    console.log(_.add(10, 20));// 输出:30
    
    
  2. 源码解读。 源码:

    const INFINITY = 1 / 0
	const symbolProto = Symbol ? Symbol.prototype : undefined
    const symbolToString = symbolProto ? symbolProto.toString : undefined
    const add = createMathOperation((augend, addend) => augend + addend, 0)
	function baseToNumber(value) {
            if (typeof value == 'number') {
               return value
           }
           if (isSymbol(value)) {
               return NAN
          }
         return +value
    }
    function isSymbol(value) {
         const type = typeof value
         return type == 'symbol' || (type == 'object' && value != null && getTag(value) == '[object Symbol]')  
    }
	
解读:
(1)在createMathOperation函数中,前三个if判断value和other是否为空,如果都为空就返回defaultValue(也就是0)。如果有一个为空,就返回另外一个不为空的值。接着判断value和other是否字符型,如果是,则调用baseToNumber。核心源代码,如下所示:

function createMathOperation(operator, defaultValue) {
        return (value, other) => {
              if (value === undefined && other === undefined) {
                      return defaultValue
               }
              if (value !== undefined && other === undefined) {
                      return value
              }
             if (other !== undefined && value === undefined) {
                      return other
             }
            if (typeof value == 'string' || typeof other == 'string') {
                     value = baseToString(value)
                     other = baseToString(other)
            }
            else {
                     value = baseToNumber(value)
                     other = baseToNumber(other)
            }
            return operator(value, other)
      }
 }

实例如下:

     const _ = require('lodash');
     console.log(_.add(undefined, undefined)) // 输出:0
     console.log(_.add(1, '')); // 输出:1

(2)在baseToString中,如果传入的参数是字符串,那么直接返回该字符串进行计算。核心代码,如下所示:
   if (typeof value == 'string') {
          return value
   }

实例如下所示:

      const _ = require('lodash');
      console.log(_.add(1, '8')); // 输出:18
      console.log(_.add(1, '-8')); // 输出:1-8

如果传入的是数组,那么将数组的元素的值返回。核心源代码如下所示。
  if (Array.isArray(value)) {
          // Recursively convert values (susceptible to call stack limits).
          return `${value.map(baseToString)}`
   }

实例代码如下所示。

      const _ = require('lodash');
      console.log(_.add(1, ['1'])); // 输出:2
      console.log(_.add(1, [1])); // 输出:2
	  
如果传入的数值是一个Symbol.iterator类型,那么就返回true,否则返回false。核心代码,如下所示。
  const symbolProto = Symbol ? Symbol.prototype : undefined
  const symbolToString = symbolProto ? symbolProto.toString : undefined
  if (isSymbol(value)) {
         return symbolToString ? symbolToString.call(value) : ''
  }
 function isSymbol(value) {
        const type = typeof value
        return type == 'symbol' || (type == 'object' && value != null && getTag(value) == '[object Symbol]')
  }

如果传入的是0 且等于无穷大,则返回-0,核心代码如下所示。

      const   INFINITY  = 1 / 0
      return (result == ‘0’ && (1 / value) == -INFINITY) ? ‘-0’ : result
	  
(3)如果传入的不是字符型,则强制转换为数值型。在baseToNumber中,先判断是否为数字类型,如果是则返回该数值。否则判断是否为Symol类型,如果是Symbol则返回非数值NAN。核心代码如下所示。

 function baseToNumber(value) {
       if (typeof value == 'number') {
               return value
        }
       if (isSymbol(value)) {
              return NAN
        }
       return +value
  }

2、ceil 1)含义:向上取舍几位有效数字 2)格式:_.ceil(number, [precision=0]) 3)源码解读。

(1)在createRound函数中,首先对精度进行判断,如果为空,就返回0,否则取精度和292的最小值。源代码如下所示。

       precision = precision == null ? 0 : Math.min(precision, 292);
	   
实例代码如下所示:
   const _ = require('lodash');
   console.log(_.ceil(2.211212121, 292)); // 输出:2.211212121
   console.log(_.ceil(2.211212121, 293)); // 输出:2.211212121

(2)接着生成一个数组,数组的长度为2,第一个元素为传入的number,第二个元素是e,源代码如下所示。 let pair =${number}e.split(‘e')

实例代码如下所示。

`console.log(`${122}e`.split('e')) // 输出:[ '122', '' ] `

接着拼接number和precision成number e precision的形式,源码如下所示。 {pair[0]}e${+pair[1] + precision}

实例代码如下所示。 let pair = `${122}e`.split('e') console.log(pair) // 输出:[ '122', '' ] console.log(`${pair[0]}e${+pair[1] + 2222}`) // 输出:122e2222

3、divide 1)含义:两个数相除 2)例子。

         console.log(_.divide(10, 3)); // 输出:3.3333333333333335
         console.log(_.divide(10, 0)); // 输出:Infinity
         console.log(_.divide(undefined, 3)); // 输出:3
		 
3)源码解读。同add方法。


**4、floor**
1)含义:向下保留n位小数(不是四舍五入)
2)例子。
```        const _ = require('lodash')
          console.log(_.floor(4.0006)); // 输出:4
          console.log(_.floor(4.59996)); // 输出:4
          console.log(_.floor(4060, -2)); // 输出:4000
           console.log(_.floor(0.046, 2)); // 输出:0.04 
		 
3)源码解读。同ceil方法。

**5、max**
1)含义:求数组的最大值。如果传入的是空数组或者非数组,将返回undefined。
2)例子。
       const _ = require('lodash');
       console.log(_.max(2, 3, 4, 8))     // 输出:undefined
       console.log(_.max([3 , 8, 9, 10, 11]))    // 输出:11
       console.log(_.max([]))       // 输出:undefined
       console.log(_.max(true))    // 输出:undefined

6、maxBy 1)含义:通过迭代器求数组的最大值。 2)例子:

           const _ = require('lodash');
            let objects = [{'n': 1}, {'n': 2}]
            console.log(_.maxBy(objects, function(o) {return o.n;})) // 输出:{n: 2}
            console.log(_.maxBy(objects, 'n')) // 输出:{n: 2}
			
3)源码解读。
(1)在maxBy开头处判断array是否为空,如果为空就返回undefine。核心源码,如下所示。
         let result
         if (array == null) {
                   return result
	     }

实例代码,如下所示。

             const _ = require('lodash');
            console.log(_.maxBy(null, function(o) {return o.n})) //输出:undefined

			
(2)接着遍历数组,然后保存最大值并返回。核心代码如下所示。
      for (const value of array) {
              let computed
              const current = iteratee(value)
              if (current != null && (computed === undefined      ? (current === current && !isSymbol(current))
                      : (current > computed)
                )) {
                        computed = current
                         result = value
                 }
      }

7、mean 1)含义:求数组的平均值 2)例子:

         const _ = require('lodash')
         console.log(_.mean([4, 2, 8, 6])); // 输出:5

3)源码解读:
(1)首先计算数组的长度,如果数组为空,长度就为0。源代码如下所示。
      const length = array == null ? 0 : array.length

(2)接着计算数组平均值。源代码如下所示。

         return length ? (baseSum(array, iteratee) / length) : NAN


然后在计算数组的和,源代码如下所示。
     function baseSum(array, iteratee) {
            let result
            for (const value of array) {
                 const current = iteratee(value)
                 if (current !== undefined) {
                          result = result === undefined ? current : (result + current)
                  }
            }
            return result
      }

8、min 1)含义:计算数组的最小值 2)实例:

        const _ = require('lodash');
        console.log(_.min([4, 2, 8, 6])); // 输出:2
        console.log(_.min([undefined, 2, 8, 6])); // 输出:2
        console.log(_.min([undefined])); // 输出: undefined
        console.log(_.min([undefined, 1])); // 输出: 1


**9、minBy**
1)含义:迭代求出数组的最小值
2)实例:
   const _ = require('lodash');
   const objects = [{'n': 1}, {'n': 2}]
   console.log(_.minBy(objects, function(o) {return o.n})); // 输出:{n: 1}
   console.log(_.minBy(objects, 'n')); // 输出:{n: 1}

3)源码分析。和maxBy类似。

10、multiply 1)含义:求两个数相乘 2)实例:

       const _ = require('lodash');
       console.log(_.multiply(12, 9)); // 输出:108

3)源码分析。类似add方法。

**11、round**
1)含义:保留n为小数,可以四舍五入。
2)实例:
        const _ = require('lodash');
        console.log(_.round(4.006)); // 输出:4
        console.log(_.round(4.006, 2)); // 输出:4.01
        console.log(_.round(4060, -2)); // 输出:4100

3)源码分析。和floor类似。

12、subtract 1)含义:减法 2)实例:

       const _ = require('lodash');
       console.log(_.subtract(10, 4)); // 输出:6

3)源码分析。类似divide。

**13、sum**
1)含义:求和
2)实例:
  const _ = require('lodash');
  console.log(_.sum([4, 3, 5, 10])); // 输出:22

3)源码分析。 首先判断数组是否为空,并且数组的长度存在。如果都不存在,则返回0。如果数组和数组长度都存在,则求数组的和。源码如下所示。 ``` function sum(array) { return (array != null && array.length) ? baseSum(array, (value) => value) : 0 }

14、sumBy 1)含义:求对象数组的和。 2)实例:

         console.log(_.sumBy([{'n': 3}, {'n': 12}, {'n': 3}], function(o) {return o.n})); // 输出:18 

3)源码分析:和sum类似。
回到顶部