我正在使用随机创建的索引将一些项插入到数组中,例如:
var myArray = new Array();
myArray[123] = "foo";
myArray[456] = "bar";
myArray[789] = "baz";
...
换句话说,数组索引不以零开头,它们之间会有“数字间隙”。我的问题是:
编辑: 关于我在插入/删除后重新定位项目的问题/关注 - 我想知道内存会发生什么,而不是索引。来自wikipedia article的更多信息:
链接列表有几个优点 在动态数组上。插入一个 列表中特定点的元素 是一个恒定时间操作,而 随机插入动态数组中 地点将需要移动一半 平均的元素,以及所有 在最坏的情况下的元素。一个人 可以从数组中“删除”一个元素 在不知何时通过某种方式标记 它的位置为“空置”,这就是原因 分裂,阻碍了 迭代的表现。
答案 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)
“差距”不会导致分配,不会,现有值不会从其索引中“转移”。