我遇到以下情况:
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的建议,有人甚至提到实现链接列表。我认为我不需要实现链表,因为我不经常添加或删除元素。
答案 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
)。
它没有设置空索引的键,这让我相信它使用更少的内存。如果您有一个数组a = [null,null,null]
或a = [undefined,undefined,undefined]
,那些数组每个都有三个索引,如果您使用a.map
或a.forEach
,则会为每个索引调用您的函数。如果您使用a = new Array(3)
然后调用a.forEach
,那么您的函数将仅调用您明确设置为构造后值的索引。
但是之间似乎没有很大的性能差异:
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数组,获取堆快照并进行比较。