const NAN = 0 / 0
/** Used to match leading and trailing whitespace. */
const reTrim = /^\s+|\s+$/g
/** Used to detect bad signed hexadecimal string values. */
const reIsBadHex = /^[-+]0x[0-9a-f]+$/i
/** Used to detect binary string values. */
const reIsBinary = /^0b[01]+$/i
/** Used to detect octal string values. */
const reIsOctal = /^0o[0-7]+$/i
/** Built-in method references without a dependency on `root`. */
const freeParseInt = parseInt
function toNumber(value) {
if (typeof value === 'number') {
return value
}
if (isSymbol(value)) {
return NAN
}
if (isObject(value)) {
const other = typeof value.valueOf === 'function' ? value.valueOf() : value
value = isObject(other) ? `${other}` : other
}
if (typeof value !== 'string') {
return value === 0 ? value : +value
}
value = value.replace(reTrim, '')
const isBinary = reIsBinary.test(value)
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value)
}
几个常量
const NAN = 0 / 0
/** Used to match leading and trailing whitespace. */
const reTrim = /^\s+|\s+$/g
/** Used to detect bad signed hexadecimal string values. */
const reIsBadHex = /^[-+]0x[0-9a-f]+$/i
/** Used to detect binary string values. */
const reIsBinary = /^0b[01]+$/i
/** Used to detect octal string values. */
const reIsOctal = /^0o[0-7]+$/i
/** Built-in method references without a dependency on `root`. */
const freeParseInt = parseInt
本文为读 lodash 源码的第五十二篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash
gitbook也会同步仓库的更新,gitbook地址:pocket-lodash
依赖
《lodash源码分析之isObject》
《lodash源码分析之isSymbol》
源码分析
整体源码
几个常量
NAN
NaN
的意思是not a number
,用0 / 0
可以返回一个NaN
值。reTrim
这个正则用来去除前后的空格
reIsBadHex
这个正则咋看起来有点奇怪,是检测形似带符号的16进制字符串,如:
+0x1f
。为什么是bad
呢,从lodash
的pr来看,应该是跟node v0.8
的某个 bug 有关。因为lodash
也支持在node
,因此需要做兼容。所以十六进制的处理跟二进制和八进制不太一样。resIsBinary
形似二进制的字符串正则,二进制以
0b
开头,后面只能是0
或者1
。reIsOctal
形似八进制的字符串正则,八进制以
0o
开头,后面只能跟0-7
的数字。处理number类型
如果为
number
类型,则不需要做转换,原样返回即可。处理Symbol类型
如果为
Symbol
类型,则直接返回NAN
。处理Object类型
规范中有规定,
object
类型有valueOf
的方法,这个方法可以返回对象的原始值,默认情况下,如果valueOf
没有返回原始值,则会返回对象本身。例如
Number(1)
的valueOf
会返回数字1
。以下的例子会返回a
:因此,首先判断
value
有没有存在valueOf
函数,如果有,则先调用valueOf
得出结果。但是,
value
可能会没有valueOf
函数,或者valueOf
函数也可能会返回一个对象,这时,需要将other
转换成string
类型,留待后面处理。处理非String类型
在处理完
Object
类型后,现在value
都是基本类型了,在这个阶段,本来可以直接用+value
来转换成number
类型的,但是字符串前后可能会有空格,直接用+value
来转换的话,会得出NaN
值,因此字符串需要单独处理。处理String类型
第一步先将
value
的前后空格移除。接下来处理二进制和八进制,直接用
parseInt
来做转换,parseInt
的第二个参数来指定进制,其实二进制、八进制也可以用+value
来转换的,有也人提了 pr,而且性能更好。本来
16
进制也可以用parseInt
来处理的,但是根据lodash
的提交来推测,用parseInt
来转换形似+0x16
或-0x16
的字符串时,会有bug,这样的字符串,预期应该返回NAN
。如果不是形似二进制、八进制或带符号的十六进制字符串,则使用
+value
来做转换。参考资料
MDN: Object.prototype.valueOf()
License
署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)
最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:
作者:对角另一面