我來閱讀lodash源碼——Math(一)

源碼註釋版javascript

這一組函數都是數學計算相關的,主要分爲三類:java

  • 加減乘除:addsubtractmultiplydivide
  • 求最大最小平均值:maxmaxByminminBysumsumBymeanmeanBy
  • 小數的四捨五入:ceilfloorround

加減乘除

在加減乘除的源碼中能夠看到這四個函數都引用了一個 createMathOpeartion 這個函數,而後是這樣使用這個函數的:git

// 加法
const add = createMathOperation((augend, addend) => augend + addend, 0)
// 減法
const subtract = createMathOperation((minuend, subtrahend) => minuend - subtrahend, 0)
// 乘法
const multiply = createMathOperation((multiplier, multiplicand) => multiplier * multiplicand, 1)
// 除法
const divide = createMathOperation((dividend, divisor) => dividend / divisor, 1)

能夠發現,它們的實現方式都是同樣的,向 createMathOperation 傳遞一個函數,這個函數就是原生的加減乘除,因此主要的仍是要看看 createMathOperation 是啥。github

createMathOperation

源碼註釋版數組

/**
 * Creates a function that performs a mathematical operation on two values.
 *
 * @private
 * @param {Function} operator The function to perform the operation.
 * @param {number} [defaultValue] The value used for `undefined` arguments.
 * @returns {Function} Returns the new mathematical operation function.
 */

從這個函數說明中能夠看出,這個函數有兩個參數:ide

  • operator:原生四則運算函數
  • defaultValue:默認值,當未傳遞參數時返回的(原生計算中通常返回 NaN

咱們拿 add 來舉例。函數

const add = createMathOperation((augend, addend) => augend + addend, 0)
const result = add(5, 3)
console.log(result) // 8

首先是經過 createMathOperation 建立一個 add 函數,而後向其傳遞參與計算的值,也就是說 createMathOperation 應該是返回一個函數,而且有兩個參數。事實上就是這樣,返回值是一個 function(value, other)value 是被加數,other 是加數。spa

在進行加減乘除運算的時候,還須要考慮一點的就是參與計算的兩個值的數據類型,是字符串仍是數字?或者是 undefined?這裏的實現方法知足如下幾個規則:code

  1. 兩個值都爲 undefined 時,返回 defaultValue
  2. 其中一個值爲 undefined 時,返回另外一個值
  3. 有一個值爲字符串時,用 baseToString 將兩個值都轉換成 string 進行計算
  4. 其它狀況,用 baseToNumber 將兩個值都轉換成 number 進行計算

undefined 和 null 在四則運算中的區別

我注意到代碼中是判斷 value === undefined,是 ===,說明這裏嚴格區分 undefinednull ,這是以前沒注意到的地方。這是爲何呢?orm

我拿原生的加減乘除作了個實驗:

console.log(1 + undefined) // NaN
console.log(1 + null) // 1
console.log(1 - undefined) // NaN
console.log(1 - null) // 1
console.log(1 * undefined) // NaN
console.log(1 * null) // 0
console.log(1 / undefined) // NaN
console.log(1 / null) // Infinity

undefined 參與計算的結果都是 NaNnull 參與計算是將它看做 0

嗯,咱們不同,每一個人都有不一樣的境遇 ~

But,why?爲啥咱們不同?

咱們知道 undefinednull 其中有一個區別是:

  • undefined 是定義了可是沒有賦值
  • null 是爲定義

若是按照這個區別,應該把 undefined 看成 0 啊,可是結果貌似不是這樣,查查規範咯

在這就看得比較清楚了,ToNumber 運算符會將 undefined 轉換成 NaN,而將 null 轉換成 +0

baseToString

源碼註釋版

/**
 * The base implementation of `toString` which doesn't convert nullish
 * values to empty strings.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */

規則:

  1. 若是 typeof 返回 string,則直接返回 value
  2. 若是是數組,則遞歸對數組中的每一項都執行 baseToString,直到不是數組爲止,返回的是一個不含 [] 的字符串,至關於 [].join('') 的結果
  3. 若是 isSymbol 判斷爲 true,則用 toString.call 來轉換
  4. 其它狀況,就直接用模板字符串的方式返回字符串

對於 isSymbol,感受還沒理解到位,先不展開說了。。。

相關文章
相關標籤/搜索