JavaScript数组随机索引的插入和删除

时间:2010-12-30 23:14:58

标签: javascript arrays

我正在使用随机创建的索引将一些项插入到数组中,例如:

var myArray = new Array();
myArray[123] = "foo";
myArray[456] = "bar";
myArray[789] = "baz";
...

换句话说,数组索引不以零开头,它们之间会有“数字间隙”。我的问题是:

  • 即使没有指定值,这些数字间隙是否会以某种方式分配(因此占用一些内存)?
  • 当我从上面的示例中删除myArray [456]时,此项目下方的项目会被重新定位吗?

编辑: 关于我在插入/删除后重新定位项目的问题/关注 - 我想知道内存会发生什么,而不是索引。来自wikipedia article的更多信息:

  

链接列表有几个优点   在动态数组上。插入一个   列表中特定点的元素   是一个恒定时间操作,而   随机插入动态数组中   地点将需要移动一半   平均的元素,以及所有   在最坏的情况下的元素。一个人   可以从数组中“删除”一个元素   在不知何时通过某种方式标记   它的位置为“空置”,这就是原因   分裂,阻碍了   迭代的表现。

3 个答案:

答案 0 :(得分:6)

  

这些数字间隙是否会以某种方式分配(因此需要一些记忆),即使它们没有指定值?

没有。 JavaScript数组根本不是真正的数组(见下文),未使用的索引不占用内存。

  

当我从上面的示例中删除myArray [456]时,此项目下方的项目会被重新定位吗?

如果您正在谈论数组索引,则取决于您如何删除它:如果您使用delete关键字,请执行。如果您使用splice功能或类似功能,是的。就内存而言,不,其他条目不会重新定位(无论如何),以及由不再存在的条目引用的任何内存(无论是delete还是splice还是{{垃圾收集器可以回收1}}或类似的东西。链接列表在JavaScript中几乎没有优于数组或普通旧对象的优势,您很少看到它们。添加到JavaScript数组(或对象)可能是一个接近恒定时间的操作(实现可能需要进行散列,可能需要对B树结构或类似的进行遍历,但这完全是特定于实现的),因为删除。

正如您所描述的那样,正如Zevon指出的那样,您可能根本不需要阵列。如果需要pop属性或其中一个依赖于它的数组函数,则实际上只需要一个数组。否则,你最好用一个普通的旧物体:

length

这是完全有效的JavaScript。您在括号(123等)中使用的值被强制转换为字符串(无论您是处理数组还是普通对象),因此密钥实际上是“123”等等(无论您是使用var obj = {}; obj[123] = "foo"; obj[456] = "bar"; obj[789] = "baz"; Array)。您甚至可以使用Object控件结构(details here)循环遍历它们。


我的意思是“......根本不是阵列”?从字面上看。 JavaScript对象是key->值映射,JavaScript数组只不过是具有键和值的对象,以及对数字字符串键和特殊for..in属性的特殊处理。虽然我们通常将数组“索引”作为数字写入,但所有属性名称都是 strings - length转换为a[0](尽管实现可以自由地优化它,只要行为仍然按照规范)。 the specification的第15.4节涵盖了这一点,该段以本段开头:

  

Array对象对某类属性名称进行特殊处理。当且仅当ToString(ToUint32(P))等于 P <时,属性名称​​ P (以String值的形式)是数组索引 / em>和ToUint32( P )不等于2 ^ 32-1。属性名称为数组索引的属性也称为元素。每个Array对象都有一个a["0"]属性,其值始终是小于2 ^ 32的非负整数。 length属性的值在数值上大于名称为数组索引的每个属性的名称;每当一个   创建或更改Array对象的属性,根据需要调整其他属性以保持此不变量。具体来说,每当添加名称为数组索引的属性时,如果需要,length属性将更改为该数组索引的数值之一;每当更改length属性时,名称为数组索引的每个属性的值都不小于new   长度会自动删除。此约束仅适用于Array对象的自身属性,并且不受可能从其原型继承的长度或数组索引属性的影响。

答案 1 :(得分:1)

  

这些数字差距是否会以某种方式存在   分配(因此需要一些   记忆)即使他们没有   分配值?

不,请参阅spec on Array's property setter

  

当我从上方删除myArray [456]时   例如,此项目下方的项目   被重新安置?

不,如果在460处有项目,则在删除456后它将保留在那里。如果您希望下面的内容正确向下移动,请使用splice方法,如下所示:

myArray.splice(456, 1)

答案 2 :(得分:1)

“差距”不会导致分配,不会,现有值不会从其索引中“转移”。