lodash源码学习之Math

一、lodash版本:4.17.5

二、函数:

1、add

1)含义:两个月相加

2) 例子。

const _ = require('lodash’);

console.log(_.add(10, 20));// 输出:30

3) 源码解读。

源码:

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)例子。

const _ = require('lodash');

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)实例:

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

3)源码分析:和sum类似。

猜你喜欢

转载自blog.csdn.net/sunfeng568202560/article/details/81433145