为什么 parseInt(8,3) == NaN 和 parseInt(16,3) == 1?

2022-08-30 01:30:34

我正在阅读这篇文章,但我对parseInt中用基数参数章节编写的内容感到困惑

table of parseInt(_, 3) outcomes

为什么是→和→?parseInt(8, 3)NaNparseInt(16, 3)1

AFAIK 8 和 16 不是以 3 为基数的数字,因此也应该返回parseInt(16, 3)NaN

the first ten base-3 natural numbers


答案 1

这是人们一直绊倒的东西,即使他们知道它。:-)出于同样的原因,您看到此内容返回 1:在第一个无效字符处停止,并返回该点具有的任何字符。如果没有要解析的有效字符,则返回 。parseInt("1abc")parseIntNaN

parseInt(8, 3)意思是“以3为基数解析”(请注意,它将数字转换为字符串;规格中的详细信息)。但在以 3 为底数的情况下,个位数只是 、 和 。这就像要求它以八进制解析一样。由于没有有效的字符,因此您得到了."8"8012"9"NaN

parseInt(16, 3)要求它以 3 为基数进行解析。由于它可以解析 ,因此它确实如此,然后它停止在 ,因为它无法解析它。所以它返回."16"161


由于这个问题引起了很多关注,并且可能在搜索结果中排名很高,因此以下是在JavaScript中将字符串转换为数字的选项的概要,以及它们的各种特性和应用程序(从我在SO上的另一个答案中提升):

  • parseInt(str[, radix])- 尽可能多地将字符串的开头转换为一个完整的(整数)数字,忽略末尾的额外字符。也是 ;将被忽略。支持可选的基数(数字基数)参数,因此 (在十六进制中)。如果没有基数,则假定为十进制,除非字符串以 (or ) 开头,在这种情况下,它将跳过这些基数并假定十六进制。(某些浏览器过去常常将以 0 开头的字符串视为八进制;该行为从未指定过,并且在 ES5 规范中明确禁止如果未找到可分析的数字,则返回。parseInt("10x")10xparseInt("15", 16)21150x0XNaN

  • parseFloat(str)- 像 ,但做浮点数,只支持十进制。同样,字符串上的额外字符将被忽略,因此(被忽略)。由于仅支持十进制,因此 is (因为解析在 )如果未找到可分析的数字,则返回。parseIntparseFloat("10.5x")10.5xparseFloat("0x15")0xNaN

  • 一元,例如 - (例如,隐式转换)使用浮点和JavaScript的标准数字表示法将整个字符串转换为数字(仅数字和小数点= 小数点; 前缀 = 十六进制; 前缀 = 八进制 [ES2015+];一些实现扩展了它,将前导视为八进制,但不是在严格模式下)。 是因为没有被忽视。 is , is , is , is 是 [ES2015+]。有一个陷阱:是,不像你想象的那样。++str0x0o0+"10x"NaNx+"10"10+"10.5"10.5+"0x15"21+"0o10"8+""0NaN

  • Number(str)- 与隐式转换完全相同(例如,像上面的一元),但在某些实现上较慢。(这并不是说这可能很重要。+


答案 2

出于同样的原因,

>> parseInt('1foobar',3)
<- 1

在文档中,取一个字符串。和parseInt

如果字符串不是字符串,则将其转换为字符串

所以 , 或 首先转换为字符串。168'1foobar'

然后

如果遇到不是指定基数中的数字的字符,它将忽略该字符和所有后续字符parseInt

这意味着它可以转换到可以转换的地方。和 将被忽略,并且仅转换前面的内容。如果没有,则返回。68foobarNaN