携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
使用说明
toNumber方法目的是将数据转换为数字类型,而实际上该方法的使用率非常高,实际项目中我们常常调用隐式转换去转换数字类型,而对于极端情况我们并不是很在意。
_.toNumber(3.2);
// => 3.2
_.toNumber(Number.MIN_VALUE);
// => 5e-324
_.toNumber(Infinity);
// => Infinity
_.toNumber('3.2');
// => 3.2
_.toNumber()
// => NaN
_.toNumber(()=>{})
// => NaN
手动实现
对于实现一个number方法,我们可以做如下处理:
function toNumber(number){
return +number
}
该方法实现主要运用了+操作符的隐式转换,直接转换为数字类型。
源码实现
lodash里的toNumber方法封装,内部主要是针对极端情况的非目标类型进行特殊处理。
/** 用作各种 `Number` 常量的引用 */
var NAN = 0 / 0;
/** 用于检测错误的有符号十六进制字符串值 */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
/** 用于检测二进制字符串值 */
var reIsBinary = /^0b[01]+$/i;
/** 用于检测八进制字符串值 */
var reIsOctal = /^0o[0-7]+$/i;
var freeParseInt = parseInt;
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = baseTrim(value);
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value);
}
toNumber方法在实现上,对于数字类型直接返回参数,而symbol类型返回NaN。
对象类型的话则进行如下处理,主要针对对象类型的数据:
- 先判断源数据参数身上的valueOf 方法是否存在,即判断valueOf 方法是否是一个函数,是对的话调用该方法并将结果存储起来,否则的话将源数据存储起来。
- 对于存储的结果,在对其进行判断,如果是对象类型,直接将第一步存储的结果转换为字符串,不是对象的话则返回第一步存储的结果。
对于非字符串类型的数据,先判断其是否等于0,是的话直接返回,否则的话返回隐式转换之后的结果。
上面的处理主要是针对特例进行if判断处理,主要针对了数字类型、symbol类型、对象类型以及非字符串类型,其余类型则在函数执行流程中处理。
可以看到在其余类型的处理如下:
- 先是处理参数,调用baseTrim方法,主要是去除字符串中头尾空格。
- 如果参数是二进制字符串值或八进制字符串值,调用freeParseInt方法。
- 如果参数是十六进制字符串值,则返回NaN,否则其他情况返回参数的隐式转换值。
var reWhitespace = /\s/;
// 匹配最后一个空白字符的索引
function trimmedEndIndex(string) {
var index = string.length;
while (index-- && reWhitespace.test(string.charAt(index))) {}
return index;
}
var reTrimStart = /^\s+/;
// 去除头尾的空白空格
function baseTrim(string) {
return string
? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
: string;
}
小结
lodash的toNumber在实现上考虑到参数的多种情况,重点处理字符串的进制问题。
其次对于对象类型,则调用对象身上的valueOf方法。
对于symbol类型则返回NaN,数字类型直接返回参数。