删除并存储数组项而不创建垃圾。

3
我正在寻找一种高效的方法来从数组中删除和存储元素。我正在尝试创建一个对象池以减少垃圾回收调用。
.pop().unshift() 从数组中移除元素并返回该元素的值类似,我希望能够删除特定索引处的元素,同时将其值存储在变量中,并且不创建不必要的数组/对象。 .splice() 可以很好地删除特定索引处的元素,并将该值存储在数组中。我可以访问该值,但函数本身会创建新数组,这最终将触发垃圾回收器。 .slice() 也有相同的问题,它会创建新的数组。
是否有一种方法可以在不创建新数组的情况下提取和存储特定索引的元素?

您的建议并没有从数组中删除该项,而是将该项更改为未定义。请在删除后查看数组长度。 - Armen
@VisioN 如果a=[0,1,2,3,4,5,6,7,8,9],那么在Firefox的scratchpad上删除a[4]会得到a=[0,1,2,3,,5,6,7,8,9],而我认为OP想要的是[0,1,2,3,5,6,7,8,9]。 - jing3142
2
@jing3142 他的意思是 Array.prototype.splice 会返回一个新数组(被移除元素的数组)。这将在后面触发垃圾回收。OP正在寻找避免这种情况的方法。 - Some Guy
1
为什么不实现一个不创建新数组的splice呢? - Esailija
1
@BenjaminGruenbaum 提到,在 JavaScript 中,链表的性能非常糟糕,除非你有一个巨大的列表并且需要在中间进行大量删除操作,否则最好使用紧凑数组。相关链接:http://kjellkod.wordpress.com/2012/02/25/why-you-should-never-ever-ever-use-linked-list-in-your-code-again/ - Esailija
显示剩余8条评论
1个回答

4

这将始终删除 index 处的一个项目,如果您需要一次删除多个连续项目,则实现它以接受 howMany 参数并批量删除它们而不是重复调用removeAt将更加高效。

function removeAt(array, index) {
    // Assumes array and index are always valid values
    // place validation code here if needed
    var len = array.length;
    // for example if index is not valid here, it will deoptimize the function
    var ret = array[index];
    for (var i = index + 1; i < len; ++i) {
        array[i - 1] = array[i];
    }
    array.length = len - 1;
    return ret;
}

使用方法:

var a = [1,2,3,4,5]
var removed = removeAt(a, 2);
console.log(a);
// [1, 2, 4, 5]
console.log(removed);
// 3

你为什么要缓存循环的长度? - Benjamin Gruenbaum
@BenjaminGruenbaum 为什么不呢? - Esailija
因为提升优化非常不可靠。 - Esailija
1
i < array.length 在循环的每次迭代中都会从内存中读取长度,而 i < len 则将长度存储在寄存器中供整个循环使用。然而,使这两者相等的优化极不可靠,因此最好每次都写 i < len - Esailija
谢谢Esailija,一个朋友推荐了类似的方法,我现在正在进行一些测试。看起来很有前途!非常感谢。我一直在寻找提高HTML5游戏性能的方法。您会推荐deque用于任何游戏使用吗? - jackrugile
显示剩余6条评论

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