开发者

Does null occupy memory in javascript?

I've got the following situation:

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

where every element of both arrays is an object.

The small array contains information related to the the larger one, but not every element of large requires an associated element in small and so I set i开发者_如何学Pythont to null. However, I do still need to keep the indices the same so I can do things like large[16].id + ': ' + small[16].description. Does the fact that I've got an array that's mostly null in value result in increased memory usage?

My question is whether or not I'd be better off doing something like small = [a2,b2,c2,i2], and setting indices in properties like a2.index = 0; b2.index = 1 and so on.

I've also come across a suggestion to use undefined instead and someone even mentioned implementing linked lists. I don't think I need to implement a linked list since I'm not adding or removing elements very often.


Arrays are actually Objects with special treatment of properties with names that are array indexes.

By assigning 'null', you bring each property into existence, which will use a non-zero amount of memory and as mentioned already slow down lookups.

You can elide the non-existent members instead, which will result in a sparse array:

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

Edit Note that undefined does take space if you explicitly assign it to an array element (or any variable). To reclaim memory in this case, you will need to explicitly delete the element. The initialization style shown in my code sample never assigns anything to the elided elements, so they do not exist at all. This can be confirmed by checking for those elements' existence as properties of the array object:

// 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.


Why not just put the small items into large[2].small? Anyway, you usually don't have to worry about memory consumption in javascript, but still it is better to leave the unused positions in small undefined (which is something else than setting them to undefined!), so that javascript engine can decide to switch to sparse array (represented by a hashtable instead of an array).


Null will consume the memory only for the size of a word 'NULL' (in terms of interpreter), but the lookup will slow down because of the array overwhelmed with objects which will not go to the lookup result, and JS does not have a way to optimize this. You should better use the array of objects, and each object should keep a value and the index.

Usage of undefined is tricky as well. In terms of interpretation and script size, this will increase a memory, but this is not a part of specs to advise whether undefined should consume memory and how much, so it is up to a browser, his facilities to garbage collect, consume memory heap etc. The best way to go is to try, probably. Run a relatively large array of both NULLs and undefined's within Chrome, take a heap snapshot and compare.


I can't fully answer your question, because I'm not sure whether null takes up as much room as explicitly setting it to undefined. But I believe the standard way to do this is to use the Array constructor:

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

I believe this uses less memory than explicitly setting values to undefined, though the effect is the same. I've used this for a sparse array with 250,000+ indices, and didn't experience any memory issues (using Google Chrome).

Edit: (after playing around and doing a little more research) Lots of folks don't like the new Array() constructor, for lots of reasons (see e.g. this discussion). But I think it has a couple of advantages for large, sparse arrays:

  • It sets the length property properly. If you need the array length to match your large array, you can't do this otherwise without setting it explicitly (small.length = large.length) or putting something undefined at the end (small[large.length-1] = undefined).

  • It doesn't set keys for empty indices, which leads me to believe it uses less memory. If you have an array a = [null,null,null] or a = [undefined,undefined,undefined], those arrays each have three indices, and if you use a.map or a.forEach your function will be called for each index. If you use a = new Array(3) and then call a.forEach, your function will only be called for the indices you've explicitly set to a value post-construction.

But there doesn't seem to be a big performance difference between:

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

and:

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

which also gives you an array of length 2000 with only one defined index. So if you don't care whether the length of small matches the length of large, I'd just use var a = [] and have it resized dynamically as necessary - from the simple perspective of setting and getting values at specific indices, it's exactly the same.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜