26

我有以下情况:

var large = [a,b,c,d,e,f,g,h,i];
var small = [a2, b2, c2, null, null, null, null, null, null, i2];

其中两个数组的每个元素都是一个对象。

小数组包含与较大数组相关的信息,但并非每个元素都large需要关联元素small,因此我将其设置为null. 但是,我仍然需要保持索引不变,这样我就可以做类似large[16].id + ': ' + small[16].description. 我有一个主要null是价值的数组这一事实是否会导致内存使用量增加?

我的问题是我是否会更好地做类似的事情small = [a2,b2,c2,i2],并在诸如此类的属性中设置索引a2.index = 0; b2.index = 1

我也遇到过使用 undefined 的建议,甚至有人提到了实现链表。我认为我不需要实现链表,因为我不经常添加或删除元素。

4

4 回答 4

20

数组实际上是对属性进行特殊处理的对象,其名称为数组索引。

通过分配“null”,您可以使每个属性都存在,这将使用非零内存量,并且如上所述会减慢查找速度。

您可以省略不存在的成员,这将导致稀疏数组:

var small = [a2, b2, c2,,,,,,, i2];
// small == [a2, b2, c2,undefined,undefined,undefined,undefined,undefined,undefined, i2]

编辑 注意,如果您将其显式分配给数组元素(或任何变量) ,undefined 则确实会占用空间。在这种情况下,要回收内存,您需要显式地显示delete该元素。我的代码示例中显示的初始化样式从未将任何内容分配给省略的元素,因此它们根本不存在。这可以通过检查这些元素是否作为数组对象的属性来确认:

// continued from above
small.hasOwnProperty('3'); // returns false

small[3] = undefined;
small.hasOwnProperty('3'); // now returns true because the property exists

delete small[3];
small.hasOwnProperty('3'); // returns false again

alert(small.length); // alerts '10', showing that the array itself is still intact.
于 2011-06-27T22:09:21.517 回答
1

为什么不把小项放到 large[2].small 中呢?无论如何,您通常不必担心 javascript 中的内存消耗,但最好将未使用的位置保留在小的 undefined 中(这与将它们设置为 undefined 不同!),以便 javascript 引擎可以决定切换稀疏数组(由哈希表而不是数组表示)。

于 2011-06-27T21:59:01.277 回答
1

我无法完全回答您的问题,因为我不确定是否null占用与明确设置为undefined. 但我相信执行此操作的标准方法是使用Array构造函数:

var large = [1,2,3,4,5,6,7];
var small = new Array(large.length);
small.length; // 7
small[0]; // undefined

我相信这比将值显式设置为未定义使用更少的内存,尽管效果是相同的。我已经将它用于具有 250,000 多个索引的稀疏数组,并且没有遇到任何内存问题(使用 Google Chrome)。

编辑:(在玩耍并进行更多研究之后)很多人不喜欢new Array()构造函数,原因有很多(参见例如这个讨论)。但我认为它对于大型稀疏数组有几个优点:

  • length正确设置了属性。如果你需要数组长度来匹配你的大数组,你不能这样做,除非明确设置它(small.length = large.length)或在末尾放置一些未定义的东西(small[large.length-1] = undefined)。

  • 它没有为空索引设置键,这让我相信它使用的内存更少。如果你有一个数组a = [null,null,null]or a = [undefined,undefined,undefined],这些数组每个都有三个索引,如果你使用a.mapor ,a.forEach你的函数将被每个索引调用。如果你使用a = new Array(3)然后调用a.forEach,你的函数只会被你显式设置为构造后值的索引调用。

似乎没有很大的性能差异:

var a = new Array(2000); 
a[2000] = 1;

和:

var = [];
a[2000] = 1;

它还为您提供了一个长度为 2000 的数组,其中只有一个已定义的索引。因此,如果您不关心 of 是否与oflength匹配small,我只需使用它并根据需要动态调整它的大小 - 从在特定索引处设置和获取值的简单角度来看,它是完全相同的。lengthlargevar a = []

于 2011-06-27T21:59:26.393 回答
1

Null 只会消耗单词 'NULL' 大小的内存(就解释器而言),但查找速度会变慢,因为数组中充满了不会进入查找结果的对象,并且 JS 没有优化这一点的方法。您应该更好地使用对象数组,并且每个对象都应该保留一个值和索引。

undefined 的使用也很棘手。在解释和脚本大小方面,这会增加内存,但这不是规范的一部分来建议 undefined 是否应该消耗内存以及消耗多少内存,所以这取决于浏览器,他的垃圾收集设施,消耗内存堆等。最好的方法是尝试,可能。在 Chrome 中运行一个相对较大的 NULL 和 undefined 数组,获取堆快照并进行比较。

于 2011-06-27T22:03:26.377 回答