lodash源码学习(13)
继续学习lodash,math部分,也就是一些数学相关的方法
“Math” Methods
_.add(augend, addend)
加法函数.
//add.js var createMathOperation = require('./_createMathOperation'); //包装方法 /** * * * @param {number} augend 相加的第一个值. * @param {number} addend 相加的第二个值. * @returns {number} 返回总值. * @example * * _.add(6, 4); * // => 10 */ var add = createMathOperation(function(augend, addend) {// 调用createMathOperation return augend + addend; }, 0); module.exports = add;
依赖于包装方法createMathOperation
//.createMathOperation.js var baseToNumber = require('./_baseToNumber'), //转化为数字 baseToString = require('./_baseToString'); //转化为字符串 /** * 闯将一个方法对两个值进行数学操作. * * @private * @param {Function} operator 需要进行的操作函数. * @param {number} [defaultValue] 默认结果值. * @returns {Function} 返回新的操作方法. * */ function createMathOperation(operator, defaultValue) { return function(value, other) { var result; if (value === undefined && other === undefined) { //如果没有传参,返回默认值 return defaultValue; } if (value !== undefined) { result = value; } if (other !== undefined) { if (result === undefined) {//如果第一个参数为undefined,返回第二个参数 return other; } if (typeof value == 'string' || typeof other == 'string') { //如果有字符串全部转换为字符串,否则全部转化为数字 value = baseToString(value); other = baseToString(other); } else { value = baseToNumber(value); other = baseToNumber(other); } result = operator(value, other);//调用操作函数 } return result;// 返回执行结果 }; } module.exports = createMathOperation;
减法,乘法,除法也是基于这个方法而来的
_.divide(dividend, divisor)
两个数值相除
//divide.js var createMathOperation = require('./_createMathOperation');//包装方法 /** * * @param {number} dividend 被除数. * @param {number} divisor 除数. * @returns {number} 返回执行结果. * @example * * _.divide(6, 4); * // => 1.5 */ var divide = createMathOperation(function(dividend, divisor) { //和add方法类似 return dividend / divisor; }, 1); module.exports = divide;
_.multiply(multiplier, multiplicand)
两个数值想乘.
//multiply.js var createMathOperation = require('./_createMathOperation'); /** * * @param {number} multiplier 相乘的第一个值. * @param {number} multiplicand 相乘的第二个值. * @returns {number} 返回执行结果. * @example * * _.multiply(6, 4); * // => 24 */ var multiply = createMathOperation(function(multiplier, multiplicand) {//和add方法类似 return multiplier * multiplicand; }, 1); module.exports = multiply;
_.subtract(minuend, subtrahend)
两个数值相减.
//subtract.js var createMathOperation = require('./_createMathOperation'); /** * * @param {number} minuend 被减数. * @param {number} subtrahend 减数. * @returns {number} 返回执行结果. * @example * * _.subtract(6, 4); * // => 2 */ var subtract = createMathOperation(function(minuend, subtrahend) {//和add方法类似 return minuend - subtrahend; }, 0); module.exports = subtract;
_.ceil(number, [precision=0])
对数值进行上舍入.
//ceil.js var createRound = require('./_createRound'); //约数构造器 /** * * @static * @memberOf _ * @since 3.10.0 * @category Math * @param {number} number 需要处理的数字. * @param {number} [precision=0] 精确的位数. * @returns {number} 返回舍入之后的数值. * @example * * _.ceil(4.006); * // => 5 * * _.ceil(6.004, 2); * // => 6.01 * * _.ceil(6040, -2); * // => 6100 */ var ceil = createRound('ceil'); //调用createRound,传入ceil module.exports = ceil;
这个方法依赖于createRound方法
//_createRound.js var toInteger = require('./toInteger'), //转化为整型 toNumber = require('./toNumber'), //转化为数字 toString = require('./toString'); //转化为字符串 /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMin = Math.min; /** * 创建一个约数方法. * * @private * @param {string} methodName 在Math方法中对应的方法名. * @returns {Function} 返回新的约数方法. */ function createRound(methodName) { var func = Math[methodName]; //对应方法 return function(number, precision) { number = toNumber(number); //转化为数字 precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); if (precision) { //用指数表示避免浮点问题 var pair = (toString(number) + 'e').split('e'), value = func(pair[0] + 'e' + (+pair[1] + precision));//先扩大10的precision倍,再调用func方法 pair = (toString(value) + 'e').split('e'); return +(pair[0] + 'e' + (+pair[1] - precision));//缩小10的precision倍,还原数值 } return func(number); }; } module.exports = createRound;
既然有ceil方法,那就必然有floor和round方法
_.floor(number, [precision=0])
对一个数值进行下舍入.
//floor.js var createRound = require('./_createRound'); /** * * @param {number} number 需要处理的数值. * @param {number} [precision=0] 精确的位数. * @returns {number} 返回处理后的数值. * @example * * _.floor(4.006); * // => 4 * * _.floor(0.046, 2); * // => 0.04 * * _.floor(4060, -2); * // => 4000 */ var floor = createRound('floor');//调用createRound,传入floor module.exports = floor;
_.round(number, [precision=0])
对一个数值进行四舍五入.
//round.js var createRound = require('./_createRound'); /** * * @param {number} number 需要处理的数值. * @param {number} [precision=0] 精确的位数. * @returns {number} 返回处理之后的数值. * @example * * _.round(4.006); * // => 4 * * _.round(4.006, 2); * // => 4.01 * * _.round(4060, -2); * // => 4100 */ var round = createRound('round');//调用createRound,传入round module.exports = round;
_.max(array)
计算数组中的最大值.
//max.js var baseExtremum = require('./_baseExtremum'), //基础求极值方法 baseGt = require('./_baseGt'), //大于比较方法,baseGt(3,1) => true, baseGt(3, 4) => false identity = require('./identity'); //返回第一个参数 /** * * @param {Array} array 需要处理的数组. * @returns {*} 返回数组中的最大值. * @example * * _.max([4, 2, 8, 6]); * // => 8 * * _.max([]); * // => undefined */ function max(array) { return (array && array.length) ? baseExtremum(array, identity, baseGt) //调用baseExtremum方法 : undefined; } module.exports = max;
依赖于baseExtremum方法
//_baseExtremum.js var isSymbol = require('./isSymbol'); /** * max和min的基本实现,接受一个比较方法决定这个极值 * * @private * @param {Array} array 需要处理的数组. * @param {Function} iteratee 对每个元素调用的迭代器. * @param {Function} comparator 比较两个值得比较方法. * @returns {*} 返回这个极值. */ function baseExtremum(array, iteratee, comparator) { var index = -1, length = array.length; while (++index < length) { //对数组进行遍历 var value = array[index], current = iteratee(value);//当前用于比较的值 if (current != null && (computed === undefined ? (current === current && !isSymbol(current)) : comparator(current, computed) )) { //对当前值和上一轮的最值进行比较 var computed = current,//当前的最值 result = value; //最值对应的元素 } } return result;//返回对应的元素 } module.exports = baseExtremum;
_.min(array)
计算数组中的最小值.
//min.js var baseExtremum = require('./_baseExtremum'), baseLt = require('./_baseLt'),//小于比较方法,baseGt(3,1) => false, baseGt(3, 4) => true identity = require('./identity'); /** * * @param {Array} 需要处理的数组. * @returns {*} 返回最小值. * @example * * _.min([4, 2, 8, 6]); * // => 2 * * _.min([]); * // => undefined */ function min(array) { return (array && array.length) ? baseExtremum(array, identity, baseLt) : undefined; } module.exports = min;
_.maxBy(array, [iteratee=_.identity])
和max方法很像,除了它接受一个遍历方法对每个元素调用,生成用于比较的值,遍历方法接受一个参数:value.
//maxBy.js var baseExtremum = require('./_baseExtremum'), baseGt = require('./_baseGt'), baseIteratee = require('./_baseIteratee'); //基础遍历方法,支持熟悉简写 /** * * * @param {Array} array 需要处理的数组. * @param {Function} [iteratee=_.identity] 遍历方法. * @returns {*} 返回对应的最大值. * @example * * var objects = [{ 'n': 1 }, { 'n': 2 }]; * * _.maxBy(objects, function(o) { return o.n; }); * // => { 'n': 2 } * * // The `_.property` iteratee shorthand. * _.maxBy(objects, 'n'); * // => { 'n': 2 } */ function maxBy(array, iteratee) { return (array && array.length) ? baseExtremum(array, baseIteratee(iteratee, 2), baseGt) //调用baseExtremum,并且传入遍历方法,和大于比较方法 : undefined; } module.exports = maxBy;
_.minBy(array, [iteratee=_.identity])
和max方法很像,除了它接受一个遍历方法对每个元素调用,生成用于比较的值,遍历方法接受一个参数:value.
//minBy.js var baseExtremum = require('./_baseExtremum'), baseIteratee = require('./_baseIteratee'), baseLt = require('./_baseLt'); /** * * * @param {Array} array 需要处理的数组. * @param {Function} [iteratee=_.identity] 遍历方法. * @returns {*} 返回对应的最小值. * @example * * var objects = [{ 'n': 1 }, { 'n': 2 }]; * * _.minBy(objects, function(o) { return o.n; }); * // => { 'n': 1 } * * // The `_.property` iteratee shorthand. * _.minBy(objects, 'n'); * // => { 'n': 1 } */ function minBy(array, iteratee) { return (array && array.length) ? baseExtremum(array, baseIteratee(iteratee, 2), baseLt) //调用baseExtremum,并且传入遍历方法,和小于比较方法 : undefined; } module.exports = minBy;
_.sum(array)
对数组元素进行求和.
// sum.js var baseSum = require('./_baseSum'), //基础求和方法 identity = require('./identity'); //返回第一个参数 /** * * @param {Array} array 需要处理的数组. * @returns {number} 返回总和. * @example * * _.sum([4, 2, 8, 6]); * // => 20 */ function sum(array) { return (array && array.length) ? baseSum(array, identity) //调用baseSum方法 : 0; } module.exports = sum;
依赖于baseSum方法
// _baseSum.js /** * 基础求和方法,不支持遍历器简写 * * @private * @param {Array} array 需要处理的数组. * @param {Function} iteratee 遍历方法,对每个元素调用. * @returns {number} 返回总和. */ function baseSum(array, iteratee) { var result, index = -1, length = array.length; while (++index < length) { //遍历数组 var current = iteratee(array[index]); //对当前值调用遍历方法 if (current !== undefined) { result = result === undefined ? current : (result + current); //执行相加 } } return result;//返回结果 } module.exports = baseSum;
_.sumBy(array, [iteratee=_.identity])
求和方法,和sum很像,除了它接受一个遍历方法对每个元素调用生成用于相加的方法.
//sumBy.js var baseIteratee = require('./_baseIteratee'), baseSum = require('./_baseSum'); /** * * @param {Array} array 需要处理的数组. * @param {Function} [iteratee=_.identity] 遍历方法. * @returns {number} 返回总和. * @example * * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; * * _.sumBy(objects, function(o) { return o.n; }); * // => 20 * * // The `_.property` iteratee shorthand. * _.sumBy(objects, 'n'); * // => 20 */ function sumBy(array, iteratee) { return (array && array.length) ? baseSum(array, baseIteratee(iteratee, 2)) //调用baseSum方法,传入遍历器,并且支持属性简写 : 0; } module.exports = sumBy;
_.mean(array)
求数组所有元素的平均值.
//mean.js var baseMean = require('./_baseMean'), //基础mean方法 identity = require('./identity'); //返回第一个参数 /** * 求数组所有元素的平均值. * * @param {Array} array 需要处理的数组. * @returns {number} 返回平均值. * @example * * _.mean([4, 2, 8, 6]); * // => 5 */ function mean(array) { return baseMean(array, identity); //调用baseMean方法 } module.exports = mean;
依赖于baseMean方法
//_baseMean.js var baseSum = require('./_baseSum'); //基础求和方法 /** Used as references for various `Number` constants. */ var NAN = 0 / 0; /** * 基础求平均值方法,不支持遍历器的简写 * * @private * @param {Array} array 需要处理的数组. * @param {Function} iteratee 遍历器对每个元素调用. * @returns {number} 返回平均值. */ function baseMean(array, iteratee) { var length = array == null ? 0 : array.length; return length ? (baseSum(array, iteratee) / length) : NAN; //调用baseSum进行求和,再进行求平均值,如果没有元素,则返回NaN } module.exports = baseMean;
_.meanBy(array, [iteratee=_.identity])
求平均值方法,和mean方法类似.除了它接受一个遍历方法对每个元素调用,生成用于计算的值,遍历方法接受一个参数:value.
// meanBy.js var baseIteratee = require('./_baseIteratee'), baseMean = require('./_baseMean'); /** * 求平均值方法,和mean方法类似.除了它接受一个遍历方法对每个元素调用,生成用于计算的值,遍历方法接受一个参数:value. * * @param {Array} array 需要处理的数组. * @param {Function} [iteratee=_.identity] 遍历器对每个元素调用。 * @returns {number} 返回这个平均值. * @example * * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; * * _.meanBy(objects, function(o) { return o.n; }); * // => 5 * * // The `_.property` iteratee shorthand. * _.meanBy(objects, 'n'); * // => 5 */ function meanBy(array, iteratee) { return baseMean(array, baseIteratee(iteratee, 2));//调用baseMean方法,传入遍历器,并且支持属性简写。 } module.exports = meanBy;