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中交易为八进制(这很奇怪..)。