使用parseInt一定要指定转换进制

960 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情

前言

如何从字符串中得到我们想要的整数?也许大多数人的想法是直接使用parseInt()这个JavaScript内置的方法,但是如果我们细想一下,这个方法的用法是什么,会不会有什么问题是目前还没有发现的。结论:使用parseInt()需要传入字符串和基数,尽管基数不是必传的,但是如果不传基数可能就会出现一些意想不到的问题。

语法

parseInt(string[,radix]),parseInt接收两个参数

string:将要被解析的值。该值需要为字符串,如果不是字符串,则会使用toString的方式将其转换为字符串。字符串前后的空白符将会被忽略

radix:表示字符串的转换基数,从2到36。指定radix为2,则表示将按照二进制的方式解析字符串;如果指定为10,则将按照10进制的方式解析字符串。需要注意的是,10不是radix的默认值,至于为什么,后文有详细的阐述。

返回值

parseInt将从给定的字符串中解析出指定或者“默认”基数的整数。如果radix小于2或者大于36,则parseInt返回NaN;如果字符串的第一个非空字符不能被转换为数字,则parseInt也返回NaN。

解析过程

  • parseInt从第一个非空格字符开始,如果第一个字符不能被转换为数字,直接返回NaN
  • 如果第一个字符是指定radix基数中的数字,例如radix指定为2,表示第一个字符只能是0或1,如果是其他值则直接返回NaN;如果radix指定为10,则表示第一个字符是十进制中的数字,即0-9,如果不是自直接返回NaN。其他的radix同理
  • 直到遇到不是radix基数中的数字,则parseInt会忽略该字符以及后续所有的字符,并返回到该点截止的已解析的整数值。也就是会产生截断
  • 某些数字在用字符串表示时会使用到e,例如1x10^20 可表示为'1e20'。但是这个值在被parseInt转换时,并不能识别e,因此会产生截断,严重丢失数据。

radix的默认值

如果radix为undefined、0或者未指定,则JavaScript会根据如下规则进行推断radix的值:

  • 如果输入的字符串的非空格字符以‘0x’或‘0X’开头,则radix会假定为16,字符串剩余的字符将按照16进制进行解析
  • 如果输入的字符串的非空格字符以‘0’开头,radix可能为8或10,具体的根据不同的浏览器版本有所差别,但是ES5中规定,此种情况radix为10。
  • 输入的字符串的非空格字符是其他开头,则radix为10

示例

parseInt('  111  ', 10); // 111,允许前导和后置空格
isNaN(parseInt('a111', 10)); // true,parseInt返回NaN,判断是否为NaN需要使用isNaN()
parseInt('111', 2); // 4+2+1=7,按照二进制解析
parseInt('211', 2); // NaN,第一个字符不符合二进制要求
parseInt('111', 8); // 64+8+1=73,按照8进制解析
parseInt('911', 8); // NaN,第一个字符不符合8进制要求

结论

  • 使用parseInt,应总是明确指定radix的值,如果未指定可能就会出现不可预见的错误
  • 使用parseInt可能会产生截断,丢失精度
  • parseInt和Math.floor类似,但两者的细分场景不太一样
  • 实际开发过程中,应尽量减少parseInt的使用,可采用Math.floor()、Number、自定义解析整数的函数来完成字符串的解析。

原创不易,转载请注明出处