•  阅读 3 分钟

parseInt() 不总是正确地转换为整数

在 JavaScript 中,所有的数字都是浮点型的,整数是没有小数的浮点数。将一个数 n 转换为整数意味着找到接近 n 的整数。你可能认为 parseInt() 能处理这项任务,但是它不能。至少,不总是有效。

parseInt() 如何工作

parseInt() 有如下定义:

parseInt(value, radix?)

它将 value 转换为字符串,然后忽略前导空格并找寻尽可能连续的整数位。

关于基数(radix)

默认值为 10,如果 radix 缺省。除非 value 以 ‘0x’ 或 ‘0X’ 开头,这种情况下 radix 的值将默认为 16(十六进制数)。

Number.parseInt('0xA') // 10

如果 radix 已经设定为 16,那十六进制前缀是可选的。

Number.parseInt('0xA', 16) // 10

Number.parseInt('A', 16) // 10

以上我们介绍了 ECMAScript 规范 定义的 parseInt() 行为。另外,一些引擎将以 0 为前缀的整数的 radix 设置为 8:

Number.parseInt('010') // 8

Number.parseInt('0109') // 8 // 忽略位数 ≥ 8

因此,最好总是明确的指定 radix

例子

一些例子:

Number.parseInt('   12', 10) // 12
Number.parseInt('12**', 10) // 12
Number.parseInt('12.34', 10) // 12
Number.parseInt(12.34, 10) // 12

最后一个例子告诉我们可以使用 parseInt() 转换数字为整数。然而,这里有一个转换错误的例子:

Number.parseInt(1000000000000000000000.5, 10) // 1

说明:parseInt 首先将参数转换为字符串。

String(1000000000000000000000.5) // '1e+21'

然后 parseInt 不识别 “e” 为整数位而停止解析 1 后面的内容。另一个例子:

Number.parseInt(0.0000008, 10) // 8

// 同理
String(0.0000008) // '8e-7'

这些限制了 parseInt() 的可用性。然而请注意,出现错误的正指数的数开始于 ±1e+21:

String(1e20) // '100000000000000000000'
String(1e21) // '1e+21'

这将远远超出 JavaScript 的整数范围 [−253, 253]

替代 parseInt() 的方法

函数 Math.trunc()toInteger()Math.round() 通常用于 number 类型。 传入这些函数的参数会隐式转换为数字类型,所以:‘80w’ => NaN,这与 parseInt() 不同。

Math.trunc()

ES6 中添加 Math.trunc() 函数用于截断数字的小数部分:

Math.trunc(80.6) // 80
Math.trunc('80.1') // 80
Math.trunc('hello') // NaN
Math.trunc(Number.NaN) // NaN
Math.trunc(undefined) // NaN

关于 Math.trunc() 博客文章 “Javascript 中的数字截断” 的介绍更详细。

toInteger()

一个好的选择是使用下面的方法,toInteger() 操作来执行 ECMAScript 规范:

function toInteger(x) {
  x = Number(x)
  return x < 0 ? Math.ceil(x) : Math.floor(x)
}

这个方法简单地移除小数部分。例如:

toInteger(3.2) // 3
toInteger(3.5) // 3
toInteger(3.8) // 3

toInteger(-3.2) // -3
toInteger(-3.5) // -3
toInteger(-3.8) // -3

Math.round()

博客 “Integers and shift operators in JavaScript” 提到几个转换数字为整数的方法。一个好的选项 Math.round(),其中 Math.round() 总是使用四舍五入的方式获取最近的整数:

Math.round(3.2) // 3
Math.round(3.5) // 4
Math.round(3.8) // 4

Math.round(-3.2) // -3
Math.round(-3.5) // -3
Math.round(-3.8) // -4

4 被认为最接近 3.5,而 -3 被认为最接近 -3.5。这与 parseInt() 行为不同。

扩展阅读

文章由 吳文俊 翻译,原文地址 parseInt() doesn’t always correctly convert to integer,转载请注明来源。

标签:
> cd ..