原帖地址:http://lifesinger.org/blog/2010/05/the-trap-of-parseint/
看代码:
alert(parseInt(0.000001)); alert(parseInt(0.0000001));
第一条语句输出 0, 第二条语句输出 1, 囧。
继续看代码:
alert(parseInt('0.000001')); alert(parseInt('0.0000001'));
都输出 0, 这才符合预期。
查看 ECMA-262 规范,parseInt 会先调用 toString 方法。问题已逐渐清晰:
alert(0.000001); alert(0.0000001);
第一条语句原样输出,第二条语句输出 1e-7.
继续翻查 ECMA-262 9.8.1 ToString Applied to the Number Type 一节,恍然大悟:
assertEquals("0.00001", (0.00001).toString()); assertEquals("0.000001", (0.000001).toString()); assertEquals("1e-7", (0.0000001).toString()); assertEquals("1.2e-7", (0.00000012).toString()); assertEquals("1.23e-7", (0.000000123).toString()); assertEquals("1e-8", (0.00000001).toString()); assertEquals("1.2e-8", (0.000000012).toString());
上面是 V8 引擎 number-tostring 的单元测试脚本 , 很好地诠释了 ECMA 规范。
小结:对于小于 1e-6 的数值来说,ToString 时会自动转换为科学计数法。 因此 parseInt 方法,在参数类型不确定时,最好封装一层:
function parseInt2(a) { if(typeof a === 'number') { return Math.floor(a); } return parseInt(a); }