iOS JavaScript引擎parseFloat(1)返回负数

这段代码会使错误出现:

function causeBug(d) { var k; var n = parseFloat(1); var c = Math.abs(d); if (n < 0) { k = '-'; } else { k = '+'; } return k + n; } $(function() { for (var i = 0; i <= 2000; ++i) { $('body').append(i + ': ' + causeBug(2) + '<br>'); } }); 

它可以在这个小提琴中看到: http : //jsfiddle.net/H2SEN/16/ (在移动Safari中查看,向下滚动,在某些时候你会看到parseFloat(1)<0)。 从第73次迭代到1500次以上,都出现了负面现象。

注意一些看起来不必要的代码,例如未使用的参数d和未使用的variablesvar c = Math.abs(d); 实际上是错误发生的必要条件。 在return语句和parseFloat调用中使用n也是如此(尽pipeparseInt也会导致它)。

只在真正的iPhone 4s(7.0.6)和两个iPod Touch(7.1testing版)上复制错误。 不在iPad或iOS模拟器,或任何桌面浏览器。 如果您启用了远程debugging并且您的计算机上打开了Safari控制台,则不会发生该错误。

我相当有信心,这是这个未答复的问题的确切原因: 移动Safari iOS 6上的奇怪的JavaScript行为

任何洞察这个错误的潜在原因将不胜感激。

JIT问题也许? 我发现在JavascriptCore源中的Math.abs的实现,我猜是不同于硝基(ios js引擎)或者可能标记为JIT可执行文件。

 Value MathFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args) { double arg = args[0].toNumber(exec); double arg2 = args[1].toNumber(exec); double result; switch (id) { case MathObjectImp::Abs: result = ( arg < 0 || arg == -0) ? (-arg) : arg; break; 

这可以直接在JavaScript中实现。 所以你可以用你的Math.abs调用来代替

 result = ( arg < 0 || arg == -0) ? (-arg) : arg; 

这将解决这个问题,并跨浏览器兼容。

提交了Apple Bug:16209709

有谁知道如何发生这种错误或更好的方式来形容它?

位翻转? 记忆碰撞? 某种types的溢出?

我build议你应该在标准中使用它。 对于parseInt ,最好传递第二个参数,如: parseInt(1, 10) 。 或者在一些IOS系统中,它会给你错误的答案。

例如, parseInt(8)将在IOS中交易为八进制(这很奇怪..)。