https://gist.github.com/4157754,這里看到的.
var a = []; //定義一個空數組
a[Math.pow(2, 32) - 2] = "最大索引"; //改變length屬性,使得a成為一個裝滿的稀疏數組.數組的最大元素個數為Math.pow(2, 32) - 1個(4294967295),由於數組索引從0開始,所以最大的索引號就是Math.pow(2, 32) - 2 console.log(a.length === Math.pow(2, 32) - 1); //true,a的length已經不能再大了 try { a.push("我比最大索引還大1", "我比最大索引還大2"); //再往里面push元素,鐵定拋出異常
} catch (e) { console.log(e instanceof RangeError); // true,數組越界 } console.log(a.length === Math.pow(2, 32) - 1); // true,長度沒變,還是4294967295,那元素呢?push進去沒有? console.log(a[Math.pow(2, 32) - 1] === "我比最大索引還大1");// true,居然能訪問,而且值還存進去了! console.log(a[Math.pow(2, 32)] === "我比最大索引還大2"); // true,這個也是! try { a.push("我比最大索引還大3?"); // 再push一個
} catch (e) { console.log(e instanceof RangeError); // true,仍然報錯 } console.log(a[Math.pow(2, 32) + 1]); //undefined,沒有存上? console.log(a[Math.pow(2, 32) - 1]) //"我比最大索引還大3?",原來是覆蓋了第一個越界的元素 console.log(a[Math.pow(2, 32)]) //"我比最大索引還大2",這個沒被覆蓋
JavaScript中的數組就是一個稍微有點特殊的普通對象.在Array.prototype.push方法執行時,會先把每個要push的元素push進去,也就是定義多個自身屬性(ES5 15.4.4.7.5).
然后才設置數組的length屬性為最大的索引值+1(ES5 15.4.4.7.5),這個例子中就是Math.pow(2, 32) + 1,這時才會報錯(ES5 15.4.5.1.3.d),但上面的元素已經push進去了.
如果再次push的話,還會從當前的length屬性-1的那個索引處開始push,也就出現了覆蓋而不是繼續追加的情況.