The entrance
const add = createMathOperation((augend, addend) = > augend + addend, 0)
Copy the code
createMathOperation
function createMathOperation(operator, defaultValue) {
return (value, other) = > {
// Exclude any value that is passed
if (value === undefined && other === undefined) {
return defaultValue
}
if(value ! = =undefined && other === undefined) {
return value
}
if(other ! = =undefined && value === undefined) {
return other
}
// There is a string type, which is converted to a string and added
if (typeof value === 'string' || typeof other === 'string') {
value = baseToString(value)
other = baseToString(other)
}
// The default conversion is number type addition
else {
value = baseToNumber(value)
other = baseToNumber(other)
}
/ / return
// The operator is (augend, addEnd) => Augend + addend
return operator(value, other)
}
}
Copy the code
Procedure: Determine the number of arguments -> Determine the type of arguments -> operation
Determine the number of arguments
The processing of undefined is used to deal with the situation that parameters are not transmitted or not transmitted
Determine the type of argument
Type to handle, string Boolean number symbol Object. The default behavior of string is to convert another value to string. For example, we usually use “+ 1” to convert other types of variables to strings. So strings require special handling
For Boolean, operations can be converted to 0 or 1 by default. If one of the values is string, it will be converted to ‘true’ and ‘false’
For symbol, have special treatment in the two methods, the string is returned to the empty string or call symbol. Prototype. ToString, number returns NaN
For the object
array
Adding the numbers will callArray.prototype.toString
By means ofbaseToNumber
After conversion, returnNaN
date
After the baseToNumber conversion, the timestamp is returned. throughbaseToString
After conversion, returns a string in local time format, such asFri Jun 18 2021 18:42:53 GMT+0800 (China Standard Time)
regexp
throughbaseToNumber
After conversion, returnNaN
. throughbaseToString
After conversion, the corresponding regular expression is returnednull
throughbaseToNumber
After conversion, return0
. throughbaseToString
Returns a string after conversion'null'
In summary, we just need to determine the number or string type to perform the operation
baseToString
/** Used as references for various `Number` constants. */
// Generate INFINITY, backward compatible
const INFINITY = 1 / 0
/** Used to convert symbols to primitives and strings. */
/ / save Symbol. Prototype. ToString references
const symbolToString = Symbol.prototype.toString
/** * The base implementation of `toString` which doesn't convert nullish * values to empty strings. * The basic toString method does not convert an invalid value to an empty string *@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.
// Do typeof value === 'string' at the beginning to ensure that in most cases value is returned directly
if (typeof value === 'string') {
return value
}
// array, recursively calls baseToString. May cause a stack overflow
if (Array.isArray(value)) {
// Recursively convert values (susceptible to call stack limits).
return `${value.map(baseToString)}`
}
/ / symbol type, called symbol. Prototype. ToString returns a string type of symbol value
// Symbol('x') => 'x'. Otherwise an empty string is returned
if (isSymbol(value)) {
return symbolToString ? symbolToString.call(value) : ' '
}
${-0} '=== = '0' true
const result = `${value}`
// -0 === 0 true
// Object.is(0, -0) false
// Handle the -0 case extra
return (result === '0' && (1 / value) === -INFINITY) ? '0' : result
}
Copy the code
baseToNumber
/** 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. * the basic implementation of 'toNumber' does not ensure the correct conversion of binary, hexadecimal, or octal string values * *@private
* @param {*} value The value to process.
* @returns {number} Returns the number.
*/
function baseToNumber(value) {
// Number type is returned directly
if (typeof value === 'number') {
return value
}
// symbol type returns NAN
if (isSymbol(value)) {
return NAN
}
// Otherwise use native toNumber for conversion
return +value
}
Copy the code
NaN, +undefined can also be generated
isSymbol
function isSymbol(value) {
// Save a reference to typeof Value
const type = typeof value
/ / to use typeof judgment, es2015, earlier versions used Object. The prototype. ToString judgment
return type == 'symbol' || (type === 'object'&& value ! =null && getTag(value) == '[object Symbol]')}Copy the code
typeof Symbol === 'function'
typeof Symbol('xx') === 'symbol'
getTag
const toString = Object.prototype.toString
/**
* Gets the `toStringTag` of `value`.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
function getTag(value) {
if (value == null) {
return value === undefined ? '[object Undefined]' : '[object Null]'
}
return toString.call(value)
}
Copy the code
Save the Object. The prototype. ToString references.
Use == null == undefined. Value = = null judgments in order to deal with the compatibility issues, since JavaScript 1.8.5 calls to null Object. The prototype. ToString returns (Object null). Calls to undefined Object. The prototype. ToString returns [Object undefined]
By changing the Object’s [Symbol toStringTag] can modify the Object. The prototype. ToString return values