整数溢出导致负数的问题

6
根据这个链接,我了解到在IE8中,如果数组的索引大于2147483647,则新元素的索引将为负数。
还有这个示例:
function test() { 
    var arr = new Array();         
    arr[2147483650] = 10000; 
    arr.push(10);     
    document.write(arr["-2147483645"] == 10); 
} 
test();

我不明白的是,为什么数组新添加的元素索引是-2147483645,我理解负数部分,只是不知道如何确定新索引是2147483645,而不是-2147483644-2147483651...
2个回答

6
在32位表示数字时,最高位用作符号位,因此当以二进制表示像2147483647这样的数字时,它是
01111...111

当有31个1时,当我们再加上一个1时,我们得到
10000...000

在这里有31个0。因此,我们已经将符号位变为1,表示一个负数。然而,由于需要避免两次表示0,我们对数字进行了包装,所以这个数字代表的不是-0,而是负2147483648(不是2147483647,因为正数一侧需要表示0,但负数一侧不需要,因此我们得到了一个“额外”的负数)。
每次加1,它都会增加二进制表示,计数器会递减到负数。
1000...00 = -2147483648 // this is 2147483648
1000...01 = -2147483647 // this is 2147483649
1000...10 = -2147483646 // this is 2147483650

“等等,因此2147483650被包装成-2147483646,因此,比这个数再多1的数被设置为-2147483645。”
“更多细节请参见这里。”

4
在你的例子中,我想指出索引值为-2147483645的数组并没有被创建,相反,你的数组被转换成了一个对象。
function test() { 
    var arr = new Array();         
    arr[2147483650] = 10000; 
    arr.push(10);     
    console.log(arr["-2147483645"] == 10); 
    console.log(arr)
} 
test();

// false
// [2147483650: 10000, 2147483651: 10]

我不理解的是,为什么新添加的数组元素具有索引-2147483645?
需要注意的是,在JavaScript中,所有东西都是对象。因此,即使是一个数组也只是一个对象。在这种情况下,你的数组实际上没有一个索引为-2147483645,事实上,没有整数溢出发生。相反,你溢出的整数被转换为字符串,并成为映射到数组对象内部值的键。
var arr = [];
arr[2147483650] = 'foo';

// The index is really just converted to a string behind the scenes
console.log(arr[2147483650] === arr["2147483650"]);

// true

如果您尝试使用超出范围的整数索引数组,它会认为您正在创建一个对象,并创建一个对象而不是索引您的数组。
var arr = [];
arr[0] = 'foo';
console.log(arr);
// ["foo"]
// Has the array notation

var arr = [];
arr[2147483650] = 'bar';
console.log(arr);
// [2147483650: "bar"]
// Notice the object notation?

1
谢谢您的回答,但这并没有回答我的问题。 - EagerToLearn
1
@N2MH Matthew很好地解释了整数溢出的工作原理,但是在使用JavaScript编程时,不要忘记如果索引溢出,则数组值可以转换为对象!祝你好运! - Nick Zuber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接