源碼學(xué)習(xí)筆記將按照l(shuí)odash源碼js文件的字母順序書(shū)寫(xiě)
add(number1, number2), 接收兩個(gè)number類(lèi)型參數(shù),非常簡(jiǎn)單,就是做加法(求和)處理,返回“和”
add.js 源碼:
import createMathOperation from './.internal/createMathOperation.js'
/**
* Adds two numbers.
*
* @since 3.4.0
* @category Math
* @param {number} augend The first number in an addition.
* @param {number} addend The second number in an addition.
* @returns {number} Returns the total.
* @example
*
* add(6, 4)
* // => 10
*/
const add = createMathOperation((augend, addend) => augend + addend, 0)
// add方法的實(shí)現(xiàn)
export default add
add.js主要是引用了createMathOperation方法, 下面貼出createMathOperation.js完整源碼
createMathOperation.js 源碼:
import baseToNumber from './baseToNumber.js'
import baseToString from './baseToString.js'
/**
* Creates a function that performs a mathematical operation on two values.
* // 創(chuàng)建一個(gè)對(duì)兩個(gè)值執(zhí)行數(shù)學(xué)運(yùn)算的函數(shù)
*
* @private
* @param {Function} operator The function to perform the operation. // 參數(shù),執(zhí)行函數(shù)
* @param {number} [defaultValue] The value used for `undefined` arguments. // 默認(rèn)值,當(dāng)未傳遞參數(shù)時(shí)返回
* @returns {Function} Returns the new mathematical operation function. // 返回一個(gè)函數(shù)
*/
function createMathOperation(operator, defaultValue) {
// value 、 other 作為箭頭函數(shù)的參數(shù)如何獲取的呢
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)
}
}
export default createMathOperation
baseToNumber.js 源碼:
import isSymbol from '../isSymbol.js'
/** Used as references for various `Number` constants. */
const NAN = 0 / 0
/**
* The base implementation of `toNumber` which doesn't ensure correct
* conversions of binary, hexadecimal, or octal string values.
*
* @private
* @param {*} value The value to process.
* @returns {number} Returns the number.
*/
function baseToNumber(value) {
if (typeof value == 'number') {
return value
}
if (isSymbol(value)) {
return NAN
}
return +value
}
export default baseToNumber
baseToString.js 源碼:
import isSymbol from '../isSymbol.js'
/** Used as references for various `Number` constants. */
const INFINITY = 1 / 0
/** Used to convert symbols to primitives and strings. */
const symbolProto = Symbol ? Symbol.prototype : undefined
const symbolToString = symbolProto ? symbolProto.toString : undefined
/**
* 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.
*/
function baseToString(value) {
// Exit early for strings to avoid a performance hit in some environments.
if (typeof value == 'string') {
return value
}
if (Array.isArray(value)) {
// Recursively convert values (susceptible to call stack limits).
return `${value.map(baseToString)}`
}
if (isSymbol(value)) {
return symbolToString ? symbolToString.call(value) : ''
}
const result = `${value}`
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result
}
export default baseToString
isSymbol.js 源碼:
import getTag from './.internal/getTag.js'
/**
* Checks if `value` is classified as a `Symbol` primitive or object.
*
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
* @example
*
* isSymbol(Symbol.iterator)
* // => true
*
* isSymbol('abc')
* // => false
*/
function isSymbol(value) {
const type = typeof value
return type == 'symbol' || (type == 'object' && value != null && getTag(value) == '[object Symbol]')
}
export default isSymbol
getTag.js 源碼:
import baseGetTag from './baseGetTag.js'
/** `Object#toString` result references. */
const dataViewTag = '[object DataView]'
const mapTag = '[object Map]'
const objectTag = '[object Object]'
const promiseTag = '[object Promise]'
const setTag = '[object Set]'
const weakMapTag = '[object WeakMap]'
/** Used to detect maps, sets, and weakmaps. */
const dataViewCtorString = `${DataView}`
const mapCtorString = `${Map}`
const promiseCtorString = `${Promise}`
const setCtorString = `${Set}`
const weakMapCtorString = `${WeakMap}`
/**
* Gets the `toStringTag` of `value`.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
let getTag = baseGetTag
// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
(getTag(new Map) != mapTag) ||
(getTag(Promise.resolve()) != promiseTag) ||
(getTag(new Set) != setTag) ||
(getTag(new WeakMap) != weakMapTag)) {
getTag = (value) => {
const result = baseGetTag(value)
const Ctor = result == objectTag ? value.constructor : undefined
const ctorString = Ctor ? `${Ctor}` : ''
if (ctorString) {
switch (ctorString) {
case dataViewCtorString: return dataViewTag
case mapCtorString: return mapTag
case promiseCtorString: return promiseTag
case setCtorString: return setTag
case weakMapCtorString: return weakMapTag
}
}
return result
}
}
export default getTag
baseGetTag.js 源碼:
const objectProto = Object.prototype
const hasOwnProperty = objectProto.hasOwnProperty
const toString = objectProto.toString
const symToStringTag = typeof Symbol != 'undefined' ? Symbol.toStringTag : undefined
/**
* The base implementation of `getTag` without fallbacks for buggy environments.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
function baseGetTag(value) {
if (value == null) {
return value === undefined ? '[object Undefined]' : '[object Null]'
}
if (!(symToStringTag && symToStringTag in Object(value))) {
return toString.call(value)
}
const isOwn = hasOwnProperty.call(value, symToStringTag)
const tag = value[symToStringTag]
let unmasked = false
try {
value[symToStringTag] = undefined
unmasked = true
} catch (e) {}
const result = toString.call(value)
if (unmasked) {
if (isOwn) {
value[symToStringTag] = tag
} else {
delete value[symToStringTag]
}
}
return result
}
export default baseGetTag