7

编辑:更简单的复制案例;以下代码:

setInterval(function(){
  var a=[10,20,30,40], i=-1;
  a[-1] = 42;
  while (i<10000) a[i++];
  console.log(a[-1],a[4294967295]);
},100);

…产生输出:

     42 undefined
     undefined 42
     42 undefined
37x  undefined 42
     42 undefined
     undefined 42
     42 undefined
41x  undefined 42
     42 undefined
     undefined 42
     42 undefined

自己试试:http: //jsfiddle.net/Fjwsg/


(原问题如下)

给定以下代码(或类似代码(小提琴)):

<!DOCTYPE HTML>
<html><head><title>-1 Array Index</title></head><body>
  <label>p: <input id="p" size="3"></label>
  <script type="text/javascript">
  var p = document.getElementById('p');
  p.onkeyup = function(){
    var a = "10 20 30 40".split(/\s+/);
    foo(a, p.value*1);
  }

  function foo(a,p){
    var count=a.length, i=0, x;
    if (p) a[i=-1]=p;
    while (i<10000) x = a[i++ % count];
    console.dir(a);
  }
  </script>
</body></html>

当我关注“p”输入并键入时,我在开发者控制台中看到以下内容1 backspace 2
数组的第一遍索引为 -1,第三遍索引为 4294967295

一旦我看到4294967295(2 32 - 1) 的索引出现,有时事情就会开始“变坏”:有时开发人员工具会自动关闭,有时所有 Safari 选项卡都会冻结并需要重新启动才能恢复。

奇怪的是,如果我删除(在这种情况下基本上没用的)while 循环,我就无法重现这个。而且我无法在 Chrome 或 Firefox 上复制它。

谁能阐明这个问题的根源可能是什么?

OS X 10.7.4 上的 Safari 5.1.7 会出现这种情况

4

2 回答 2

3

使用负索引可能会导致未定义的行为。

根据ECMAScript 文档,特定值p只能是数组索引,当且仅当:

(p >>> 0 === p) && (p >>> 0 !== Math.pow(2, 32) - 1)

在你的情况下:

# -1 >>> 0
4294967295
# Math.pow(2, 32) - 1
4294967295

编辑

如果p上述测试失败,则应将其视为常规对象属性,例如a.fooor a['foo']。也就是说,事实证明,使用字符串强制转换设置负索引可以解决这个问题。

a['' + (i =-1)] = p

结论:浏览器错误

于 2012-05-17T02:36:48.227 回答
2

对我来说,这听起来像是 JavaScriptCore 中的一个错误。可能foo在第二次调用时被 JITted 并且 JITted 代码引入了错误。

我建议针对 JavaScriptCore提交一个错误并附加您的测试用例。

于 2012-05-17T02:39:53.403 回答