IE6/7/8中parseInt第一个参数为非法八进制字符串且第二个参数不传时返回值为0

JavaScript中数字有十进制、八进制、十六进制。以"0"开头的是八进制,"0x"或"0X"开头的是十六进制。

parseInt用来把字符串转换成整型数字,它接受两个参数,第一个参数为字符串,第二个为数字基数如8,10,16。

parseInt(string, radix)

 

当第二个参数不传时默认为10,即默认转成十进制的数字。

parseInt('7')   // number 7
parseInt('8')   // number 8
parseInt('9')   // number 9

这三行代码在所有浏览器中都表现一致。

 

但第一个参数如果所传的是非法八进制数字,且第二个参数不传时,IE6/7/8将返回0,其它浏览器会忽略0返回,返回0后的数字。

parseInt('08') // IE678返回0,其它浏览器返回8
parseInt('09') // IE678返回0,其它浏览器返回9

0开头的为八进制,八进制只有0-7,"08", "09"显然是非法的八进制形式。IE6/7/8中返回的是0, 其它浏览器是8,9。

 

当然,如果是合法的八进制形式,IE6/7/8处理和其它浏览器一致,如

parseInt('01') // 1 
parseInt('07') // 7

 

这应该算IE6/7/8的bug,IE9+的处理已经和Firefox/Chrome一致了。看下ES3规范

 

当radix为undefined或0时,且string不是以0x或0X开头则按十进制处理。显然,'08', '09'不是以 '0x' 或 '0X' 开头。IE6/7/8按八进制处理,8,9是非法的八进制数字,引擎忽略返回了0。

 

可以利用这个特性判断浏览器是否是IE6,7,8

var isIE678 = parseInt('08') === 0;

   

除此之外,parseInt有一下特征(所有浏览器都一样)

一、radix 不传或为假值时,默认按10进制处理 (JS六个假值)

alert(parseInt('9')) // 9
alert(parseInt('9', null)) // 9
alert(parseInt('9', undefined)) // 9
alert(parseInt('9', 0)) // 9
alert(parseInt('9', '')) // 9
alert(parseInt('9', NaN)) // 9
alert(parseInt('9', false)) // 9

 

二、默认会忽略左右空白符

alert(parseInt(' 9')) // 9
alert(parseInt('9 ')) // 9
alert(parseInt(' 9 ')) // 9

  

三、但不会去掉中间的空白符,且默认忽略中间空白符后所有的字符

alert(parseInt('9 0')) // 9
alert(parseInt(' 9 0 ')) // 9
alert(parseInt(' 9 a ')) // 9

 

四,以"0x"或"0X"开头的字符串一律按16进制处理,无论第二个参数radix传或不传或任意值

alert(parseInt('0xa'))     // 10
alert(parseInt('0xa'), 8)  // 10
alert(parseInt('0xa'), 16) // 10

alert(parseInt('0Xa'))     // 10
alert(parseInt('0Xa'), 8)  // 10
alert(parseInt('0Xa'), 16) // 10

 

最后附上ES5里parseInt的伪码实现 (parseInt 内部执行流程)

1 调用toString(string) ,即先把第一个参数转成字符串。
2 去掉string的两边空白符,赋值给S,如果 S 不包含一个字符,那么令S为空字符串。
3 令 sign = 1
4 如果 S 不是一个空字符串,且第一个字符为负号 "-", sign赋值为-1。
5 如果 S 不是一个空字符串,且第一个字符为正号 "+" 或负号 "-",去掉正负号。如 "+30" 变为了"30", "-30"变为"30"。
6 令 R = ToInt32(radix)
7 stripPrefix = true
8 R不为0时,如果 R < 2 或 R > 36,直接返回NaN,如果 R != 16,令 stripPrefix = false
9 R为0时,令 R = 10
10 stripPrefix为true时, 如果 S 的长度length大于2切前两个字符是"0x"或"0X",那么去掉 S 的前两个字符("0x"|"0X"),令R = 16。
11 如果 S 包含的任意字符不是一个有效的 radix-R 数字(比如"8"就不是一个有效的八进制数字),令 Z 为非有效进制数字前的字符,否则令 Z = S。
12 如果 Z 是一个空字符串,返回NaN。
13 令 mathInt 为由字符串 Z 指定的 radix-R进制的数字,使用A-Z和a-z替代数字10-35。
14 令 number 为数字类型的mathInt
15 返回 sign*number

 

posted on 2014-05-14 16:34  snandy  阅读(2650)  评论(2编辑  收藏  举报