Skip to content

转化为数字类型的常用方法

转化为数字类型的常用方法

其实转化数字有常规的三种方式

  1. Number: 可以其他类型转化为数字类型;
  2. ParseFloat: 主要是将字符串转化为数字类型;
  3. ParseInt:主要是将字符串转化为数字类型;

Number

其实和运算符隐式转化数字是相同的转换规则 +'' === Number('')

typeof NaN === 'number'

  1. 将其他类型转化为数字:

    // 非字符串类型转化为数字, 常规来说, 遵循 falsy ---> 0 true truthy --- > 1 的规则
    Number(true); // 1
    Number(false); // 0
    Number(null); // 0
    // 这里有两种特殊情况
    Number(NaN); // NaN
    Number(undefined); // NaN
  2. 将字符串转化为数字,按照十进制进行转化:

    // 1. 字符串全部为数字就直接转化
    Number("111"); // 111
    // 2. 忽略前面的 0
    Number("000123"); // 123
    // 3. 它可以自动识别 2,8,16 进制的数字(字符串),并将其转化为十进制
    Number("0x123"); // 291
    Number("0b101"); // 5
    Number("0o15"); // 13
    // 4. 如果字符串中包含转化不了为数字的项, 就会被转化为 NaN
    Number("0b13"); // NaN 2 进制中不能有 3
    Number("0o9"); // NaN 8 进制中不能有 9
    Number("12za"); // NaN 'za' 无法被转化为数字

ParseInt

将目标参数(一般是字符串类型)按照一定规则转化为 10 进制数。

如果想转化其他类型(非数字,非字符串类型)为数字,那结果都是NaN

parseInt(true) === NaN, parseInt(null) === NaN ...

如果输入数字的话,直接返回数字的整数有效部分。

// 1. 可以转化字符串中前面连续的可以转化为数字的部分, 并将其作为结果返回
parseInt("123a"); // 123
parseInt("1a23a"); // 1
// 2. 如果开头就是无法转化为数字的字符, 那么直接返回 NaN
parseInt("a123"); // NaN
// 3. 忽略前面的空格还有 +- 符号,还会忽略前面的字符 0
parseInt(" +123"); // 123
parseInt(" -123"); // -123
parseInt("000101"); // 101
// 4. 它也能够识别格式正确的进制数字符串,并将其转化为 10 进制
parseInt("0x123"); // 291
parseInt("0b101"); // 5
parseInt("0o15"); // 13
// 5. 可以指定目标字符按照几进制来解析,也就是设置底数(基数), 默认底数是 10,也就是 10 进制
parseInt("0101"); // 101 默认按照 10 进制解析
parseInt("0101", 10); // 101 指定按照 10 进制来解析
parseInt("0101", 2); // 5
parseInt("0101", 8); // 65 指定按照 8 进制来解析
parseInt("0101", 16); // 257 指定按照 16 进制来解析

总结:

  1. parseInt它相比于Number更专注于处理字符串,数字,parseInt将所有的非字符串和非数字类型的直接识别为NaN

  2. parseInt(str)解析str是从左往右依次解析,会忽略空格,如果有多个无意义的0也会忽略。

    在解析过程中,如果第一个直接就是无法转换的字符,那么解析直接终止,直接返回NaN

    如果是在中间过程遇见无法转换的字符,那么解析终止,将前面的解析好的字符转换为数字作为结果返回。

    比如:

    isNaN(parseInt('a123')) === true

    parseInt('1a23') === 1

    parseInt('1.23') === 1

    这里其实是parseIntparseFloat的区别,前者将.直接识别为无法转换的字符,而后者能够将遇到的第一个.识别为小数点进行正常解析;

  3. 可以传第二个参数,基数(也就是让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

  4. 如果第一个参数不是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)这种结果为浮点型数字的来进行比较。

如果是数字的话,返回数字的有效部分。

  1. parseFloat当从左往右依次解析时,能够将遇见的第一个.识别为小数点,但是如果遇见第二个.也会终止解析,直接返回前面解析好的数字:

    parseFloat('122.345.1') ---> 122.345

    parseInt就无法这样,它遇见.直接终止解析,返回前面解析完的结果:

    parseInt('122.345.1') ---> 122

  2. parseFloat无法按照正确的解析规则解析除了10进制之外的数字(字符串):

    parseFloat('0b11') === 0; parseFloat('0o1') === 0; parseFloat('0xf') === 0

    它会将其当非法字符从而终止转化,然后截取结果返回。

    parseInt能够自动识别比如16进制的数字(用字符串表示),并将其转化为10进制:

    parseInt('0xf') === 15

  3. parseFloat无法指定第二个参数,也就是parseFloat一般只能用来给10进制的数字(字符串)来进行操作。

    parseInt可以指定第二个参数,可以进行指定将目标数字(字符串)按照几进制来解析;

  4. parseFloat如果小数点后面全部是0,那么结果会返回整数parseFloat('1.0000') === 1

封装成函数

// 这是 vue3 中工具函数的转化方式
const toNumber = (val) => {
const n = parseFloat(val);
return isNaN(n) ? val : n;
};
// 由上文结果可以知道, (如果排除这里 vue 自己的应用场景)这里用 parseFloat 是有问题的, 比如如果参数为字符串类型, 然后代表的是其他进制的数字, 转换就会出现非预期的情况:
toNumber("0xf"); // 0 期望情况: 15
toNumber("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"); // 15
toNumber("0b11"); // 3
toNumber("abc"); // 9
toNumber("123.22a"); // 123.22
toNumber("123.22a.aa"); // 123.22
toNumber("123aa"); // 123