0

I'm looking for an easy and efficient way to pigeon-hole business objects to be recalled later by ID in some sort of dictionary. I have this method working but it appears it may be unnecessarily using a lot of memory.

var objects = [{ ID: 20, Description: 'Item 1'},
               { ID: 40, Description: 'Item 2'},
               { ID: 60, Description: 'Item 3'}];

var objectsByID = [];
$.each(objects, function (index, o) {
        objectsByID[o.ID] = o;
});

var itemID40 = objectsByID[40];

Firebug tells me that objectsByID has undefined array elements in-between the ID numbers that have been added, like so:

[undefined, ... ,
Object { ID=20, Description="Item 1"}, ... ,
Object { ID=40, Description="Item 2"}, ... ,
Object { ID=60, Description="Item 3"}]

Are these array indexes actually assigned and using memory, or is this a conceptual view?
Also, should I be doing this?

1
  • Yep, used here to simplify the example code. This question isn't specifically about jQuery, I'll accept an answer that doesn't use it too. Commented Jan 21, 2011 at 10:34

2 Answers 2

3

JavaScript arrays are sparse, so no, you're aren't taking up extra memory like that. The downside though, and the reason why consoles display it like that, is that the length property will be equal to your highest index + 1.


Some explanation:

All array indices are converted into strings and treated exactly the same as object properties. You can do the following test in the console:

var a = [];
a[100] = "hello";

a["100"]; // "hello"
a.hasOwnProperty("100"); // true
a.hasOwnProperty("0"); // false

To show that this isn't the same as a property that's declared but 'undefined':

a[0] = undefined;
a.hasOwnProperty("0"); // true
Sign up to request clarification or add additional context in comments.

6 Comments

I believe that for performance reasons, most JS implementations assume that the normal use case is a compact array and are implemented as such.
@spender, that would be an incorrect implementation then, and most JS implementations (i.e. the browsers) don't implement it as such. Please try out the code I posted to see for yourself.
OK. After a little testing, I'm coming round to your POV. For instance, I would have expected the following code snippet to kill my machine if my assertions were correct: var a=[]; a[1000000000]=1; alert(a[1000000000]);
@Box9, You are right: var a = [];a[0] = 1;a[12] = 12;a[22] = 22;a[2] = 2; console.log(a.sort()); produces a result that proves your point. An eyeopener this morning ;) Thanks!
@spender, I'm glad, and that's a good way to demonstrate it too - I'll have to remember that :)
|
1
var objects = {
    "20": { ID: 20, Description: "Item 1" }
    "40": { ID: 40, Description: "Item 2" }
}

Don't use an array. Use an object and duplicate the key. You can still treat it as an array but with an array it will create spaces 1-19 here you just have two keys which happen to be called "20" and "40".

Of course you can just use arrays anyway because it doesn't really matter that much in terms of memory usage with a bunch of undefined objects. We don't allocate blocks of memory equivelant to the largest block in the array like we do in C.

6 Comments

I would have to drop my use of JavaScriptSerializer to do this, but it does seem like the most direct approach. Thanks!
You should be able to serialize a C# object on the codebehind like an IDictionary with key,values of (20, BusinessObject) using JavaScriptSerializer.
This works like a charm! I had to declare the dictionary as Dictionary<string,object> because it needs to serialize the key as a property name (string) and I was using a .Select() translation from my business object to an anonymous type to ensure I wasn't serializing all the stuff I don't need. Great answer, although technically @Box9's answer is a more appropriate answer to my question, this answer is the one I will be using. Cheers!
@Codesleuth, good choice to go with the object. Just keep in mind that objects and arrays behave exactly the same, except that arrays have a .length and methods like .push(), .pop(), .slice() that only make sense if the keys are integers. The decision whether to use an object or an array should depend on whether these extra properties/methods are needed, and also whether ordering is important.
@Raynos I am using .data() to put the objects where I will need them on the client, which is why I needed to get objects by ID in the first place, to reduce the load on the client when searching for objects in the [former] array. Once this is all done, I shouldn't be needing the objects in this form any more, so this serves its purpose well. Cheers!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.