null是否占用javascript中的内存?

时间:2011-06-27 21:51:03

标签: javascript memory sparse-array

我遇到以下情况:

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 个答案:

答案 0 :(得分:16)

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

通过指定'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. 元素。我的代码示例中显示的初始化样式从不将任何分配给elided元素,因此它们根本不存在。这可以通过检查这些元素是否作为数组对象的属性来确认:

{{1}}

答案 1 :(得分:1)

为什么不将小物品放入大型物品[2]。小?无论如何,你通常不必担心javascript中的内存消耗,但仍然最好将未使用的位置保留为小的未定义(这不是将它们设置为未定义!),以便javascript引擎可以决定切换稀疏数组(由哈希表而不是数组表示)。

答案 2 :(得分: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

我认为这比使用undefined明确设置值使用更少的内存,尽管效果是相同的。我已经将它用于具有250,000多个索引的稀疏数组,并且没有遇到任何内存问题(使用谷歌浏览器)。

编辑:(在玩完并进行更多研究之后)很多人不喜欢new Array()构造函数,原因很多(参见例如this discussion )。但我认为它对于大型稀疏数组有一些优势:

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

    < / LI>
  • 它没有设置空索引的键,这让我相信它使用更少的内存。如果您有一个数组a = [null,null,null]a = [undefined,undefined,undefined],那些数组每个都有三个索引,如果您使用a.mapa.forEach,则会为每个索引调用您的函数。如果您使用a = new Array(3)然后调用a.forEach,那么您的函数将调用您明确设置为构造后值的索引。

    < / LI>

但是之间似乎没有很大的性能差异:

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

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

为您提供一个长度为2000的数组,只有一个已定义的索引。因此,如果您不关心length的{​​{1}}是否与small的{​​{1}}匹配,我只会使用length并将其动态调整为必要 - 从设置和获取特定指数值的简单角度来看,它完全相同。

答案 3 :(得分:1)

Null将仅消耗单词'NULL'(就解释器而言)的大小而占用内存,但是由于数组被不会进入查找结果的对象所淹没,查找将变慢,而JS没有办法优化这个。 你应该更好地使用对象数组,每个对象应该保留一个值和索引。

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