转化为数字类型的常用方法
转化为数字类型的常用方法
其实转化数字有常规的三种方式
Number
: 可以其他类型转化为数字类型;ParseFloat
: 主要是将字符串转化为数字类型;ParseInt
:主要是将字符串转化为数字类型;
Number
其实和运算符隐式转化数字是相同的转换规则
+'' === Number('')
。
typeof NaN === 'number'
。
-
将其他类型转化为数字:
// 非字符串类型转化为数字, 常规来说, 遵循 falsy ---> 0 true truthy --- > 1 的规则Number(true); // 1Number(false); // 0Number(null); // 0// 这里有两种特殊情况Number(NaN); // NaNNumber(undefined); // NaN -
将字符串转化为数字,按照十进制进行转化:
// 1. 字符串全部为数字就直接转化Number("111"); // 111// 2. 忽略前面的 0Number("000123"); // 123// 3. 它可以自动识别 2,8,16 进制的数字(字符串),并将其转化为十进制Number("0x123"); // 291Number("0b101"); // 5Number("0o15"); // 13// 4. 如果字符串中包含转化不了为数字的项, 就会被转化为 NaNNumber("0b13"); // NaN 2 进制中不能有 3Number("0o9"); // NaN 8 进制中不能有 9Number("12za"); // NaN 'za' 无法被转化为数字
ParseInt
将目标参数(一般是字符串类型)按照一定规则转化为
10
进制数。如果想转化其他类型(非数字,非字符串类型)为数字,那结果都是
NaN
。
parseInt(true) === NaN, parseInt(null) === NaN ...
如果输入数字的话,直接返回数字的整数有效部分。
// 1. 可以转化字符串中前面连续的可以转化为数字的部分, 并将其作为结果返回parseInt("123a"); // 123parseInt("1a23a"); // 1
// 2. 如果开头就是无法转化为数字的字符, 那么直接返回 NaNparseInt("a123"); // NaN
// 3. 忽略前面的空格还有 +- 符号,还会忽略前面的字符 0parseInt(" +123"); // 123parseInt(" -123"); // -123parseInt("000101"); // 101
// 4. 它也能够识别格式正确的进制数字符串,并将其转化为 10 进制parseInt("0x123"); // 291parseInt("0b101"); // 5parseInt("0o15"); // 13
// 5. 可以指定目标字符按照几进制来解析,也就是设置底数(基数), 默认底数是 10,也就是 10 进制parseInt("0101"); // 101 默认按照 10 进制解析parseInt("0101", 10); // 101 指定按照 10 进制来解析parseInt("0101", 2); // 5parseInt("0101", 8); // 65 指定按照 8 进制来解析parseInt("0101", 16); // 257 指定按照 16 进制来解析
总结:
-
parseInt
它相比于Number
更专注于处理字符串,数字,parseInt
将所有的非字符串和非数字类型的直接识别为NaN
-
parseInt(str)
解析str
是从左往右依次解析,会忽略空格,如果有多个无意义的0
也会忽略。在解析过程中,如果第一个直接就是无法转换的字符,那么解析直接终止,直接返回
NaN
。如果是在中间过程遇见无法转换的字符,那么解析终止,将前面的解析好的字符转换为数字作为结果返回。
比如:
isNaN(parseInt('a123')) === true
;parseInt('1a23') === 1
;parseInt('1.23') === 1
;这里其实是
parseInt
和parseFloat
的区别,前者将.
直接识别为无法转换的字符,而后者能够将遇到的第一个.
识别为小数点进行正常解析; -
可以传第二个参数,基数(也就是让
parseInt
将目标字符当作几进制的数字来解析)。如果不传的话,将其按照
10
进制来解析,当然,如果有特殊进制标识,parseInt
也能识别。比如
parseInt
可以自动识别16
进制,将其转化为10
进制。parseInt('0x123') // 291
,按照16
进制解析为10
进制。无法自动识别其他进制的字符串:
parseInt('0b11') === 0
;parseInt('0o11') === 0
;当然,这里如果你传入数字的话,会直接返回整数有效部分:
parseInt(0b11) === 3
;parseInt(0o11) === 19
;这里的理解方式是,当你写出
0b11, 0o11, 0xf0
的时候,V8
在编译解释的时候就将其转化为十进制数字了,也就是这里我们的写法实际等同:parseInt(3) === 3
;parseInt(19) === 19
; -
如果第一个参数不是
10
进制数字,那么先转化为10
进制数,然后按照基数解析:parseInt(0b11, 8) === 3 ---> 0b11 转化为 10 进制 3,然后按照 8 进制来解析,还是 3
;parseInt(0xf, 8) === 13 ---> 0xf 转化为 10 进制 15,然后按照 8 进制来解析,就是 13
;
ParseFloat
和
parseInt
目标差不多,不过parseFloat
一般是用来转化浮点型的。它大部分和
parseInt
类似,接下来就讲讲他和parseInt
的区别。备注一下:任何数字只要和浮点型进行运算,都有可能会出现精度溢出的情况,并且最好不要用类似于(
0.1 + 0.2 === 0.3
)这种结果为浮点型数字的来进行比较。如果是数字的话,返回数字的有效部分。
-
parseFloat
当从左往右依次解析时,能够将遇见的第一个.
识别为小数点,但是如果遇见第二个.
也会终止解析,直接返回前面解析好的数字:parseFloat('122.345.1') ---> 122.345
;parseInt
就无法这样,它遇见.
直接终止解析,返回前面解析完的结果:parseInt('122.345.1') ---> 122
; -
parseFloat
无法按照正确的解析规则解析除了10
进制之外的数字(字符串):parseFloat('0b11') === 0; parseFloat('0o1') === 0; parseFloat('0xf') === 0
;它会将其当非法字符从而终止转化,然后截取结果返回。
parseInt
能够自动识别比如16
进制的数字(用字符串表示),并将其转化为10
进制:parseInt('0xf') === 15
; -
parseFloat
无法指定第二个参数,也就是parseFloat
一般只能用来给10
进制的数字(字符串)来进行操作。parseInt
可以指定第二个参数,可以进行指定将目标数字(字符串)按照几进制来解析; -
parseFloat
如果小数点后面全部是0
,那么结果会返回整数parseFloat('1.0000') === 1
;
封装成函数
// 这是 vue3 中工具函数的转化方式const toNumber = (val) => { const n = parseFloat(val); return isNaN(n) ? val : n;};// 由上文结果可以知道, (如果排除这里 vue 自己的应用场景)这里用 parseFloat 是有问题的, 比如如果参数为字符串类型, 然后代表的是其他进制的数字, 转换就会出现非预期的情况:toNumber("0xf"); // 0 期望情况: 15toNumber("0b11"); // 0 期望情况: 3
// 修改之后// 判断是否是其他进制const isOtherBaseNumberRE = /^0[bBoOxX]\d+/;const toNumber = (val) => { val = val ?? ""; let n; // 如果 test 的参数是 Number, 会自动转化为'' // 这里利用 Number 可以识别其他进制,并且将之转化为 10 进制的能力 n = isOtherBaseNumberRE.test(val) ? Number(val) : val; if (typeof n !== "number") { n = n.includes(".") ? parseFloat(n) : parseInt(n); } let res = isNaN(n) ? val : n; console.log("res: ", res); return res;};toNumber("0xf"); // 15toNumber("0b11"); // 3toNumber("abc"); // 9toNumber("123.22a"); // 123.22toNumber("123.22a.aa"); // 123.22toNumber("123aa"); // 123