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/(在Mobile Safari中查看,向下滚动,在某些时候你会看到parseFloat(1)< 0).从第73次迭代到超过1500次,任何地方都发现了负面消息. 注意一些看似不必要的代码,例如未使用的参数d和未使用的变量var c = Math.abs(d);实际上是发生错误所必需的.对于在return语句中使用n和parseFloat调用(尽管parseInt也会导致它)也是如此. Bug仅在真正的iPhone 4s(7.0.6)和两个iPod Touch(7.1 beta)上再现.不在iPad或iOS模拟器或任何桌面浏览器中.如果启用了远程调试并在计算机上打开了Safari控制台,则不会出现此错误. 我相信这是这个悬而未决的问题的确切原因:Strange JavaScript behaviour on mobile Safari iOS 6

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

解决方法

也许是JIT问题?我在JavascriptCore源代码中发现了Math.abs的实现,我猜测它与Nitro(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

有谁知道这种错误是如何发生的或更好的描述方式?

比特翻转?记忆碰撞?某种溢出?

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...