编辑:更简单的重复案例;以下代码:
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
(原始问题如下)
给出以下代码(或code like it (fiddle)):
<!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 退格 2 时,我在Developer Console中看到以下内容:
一旦我看到4294967295
(2 32 - 1)的索引出现,事情有时会开始“变坏”:有时开发人员工具会自动关闭,有时候所有的Safari标签都会关闭冻结并需要重新启动才能恢复。
奇怪的是,如果我在循环中删除(在这种情况下很大程度上无用),我无法重复此操作。我无法在Chrome或Firefox上重复此操作。
任何人都可以对这个问题的根源有什么看法吗?
OS X 10.7.4
上的Safari 5.1.7会出现这种情况答案 0 :(得分:3)
使用否定索引可能会导致未定义的行为。
根据ECMAScript documentation,当且仅在以下情况下,特定值p
只能是数组索引:
(p >>> 0 === p) && (p >>> 0 !== Math.pow(2, 32) - 1)
在你的情况下:
# -1 >>> 0
4294967295
# Math.pow(2, 32) - 1
4294967295
修改强>
如果p
未通过上述测试,则应将其视为常规对象属性,例如a.foo
或a['foo']
。也就是说,事实证明,使用字符串转换设置负索引可以解决问题。
a['' + (i =-1)] = p
结论:浏览器错误
答案 1 :(得分:2)
这听起来像是JavaScriptCore中的一个错误。当foo
被第二次调用并且JITted代码引入错误时,{{1}}可能正在被JIT。
我建议您针对JavaScriptCore filing a bug添加测试用例。