1. 程式人生 > >lodash源碼學習(13)

lodash源碼學習(13)

identity 依賴 als sta rem ports use 極值 位數

繼續學習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;

lodash源碼學習(13)