0

I have a strange problem. I need a multidimensional javascript array that has numeric indexes e.g.:

  MyArray = new Array();

  $(".list-ui-wrapper").each(function(){
       var unique = $(this).attr('id').replace(/[^\d.]/g,'');
       MyArray ["'"+unique+"'"] = new Array();
  });

The unique is a 8 digit integer. So if I dont wrap it inside the quotes, the ListUI_col_orders array will become extremly big, because if the unique = 85481726 then javascript will fill the array with 85481725 undefined elements before the the new empty array at the 85481726th index.

My problem is that later if i generate the unique again i cannot access the array anymore:

var unique = $(this).attr('id').replace(/[^\d.]/g,'');
console.log(MyArray [unique]); // undefined
console.log(MyArray ['"'+unique+'"']); // undefined
console.log(MyArray [unique.toString()]); // undefined

Any tips?

3
  • "... because if the unique = 85481726 then javascript will fill the array with 85481725 undefined elements before the the new empty array at the 85481726th index." No, it won't. JavaScript standard arrays are sparse. Setting an element at index 85481725 results in an array with one entry, and a length value of 85481726. That's all it does. More: A myth of arrays Commented Mar 7, 2014 at 14:38
  • @Jon: Actually, it does, because the OP ends up with keys with single quotes at the beginning and end; but then later the OP tries to retrieve the value without the single quotes. No matching key, and therefore he/she doesn't get the value back. Commented Mar 7, 2014 at 14:59
  • @T.J.Crowder: Argh. I was curious and quickly made a small test in the FF console but I totally bungled it -- x['2'] = 1; alert(x[2]); instead of the correct x["'2'"] = 1. Don't know what I was thinking. My excuse is brainfart. Commented Mar 7, 2014 at 15:03

2 Answers 2

2

...because if the unique = 85481726 then javascript will fill the array with 85481725 undefined elements before the the new empty array at the 85481726th index.

No, it won't. JavaScript standard arrays are sparse. Setting an element at index 85481725 results in an array with one entry, and a length value of 85481726. That's all it does. More: A myth of arrays

The problem is that you're trying to retrieve the information with a different key than the key you used to store it. When storing, you're using a key with single quotes in it (actually in the key), on this line of code:

MyArray ["'"+unique+"'"] = new Array();

Say unique is 85481726. That line then is equivalent to this:

MyArray ["'85481726'"] = new Array();

Note that the key you're using (the text between the double quotes) has ' at the beginning and end. The actual property name has those quotes in it. Since it doesn't fit the definition of an array index, it doesn't affect length. It's a non-index object property. (How can you add a property to an array that isn't an array index? Arrays are not really arrays, see the link above.)

Later, you never use that key when trying to retrieve the value:

var unique = $(this).attr('id').replace(/[^\d.]/g,'');
console.log(MyArray [unique]); // undefined
console.log(MyArray ['"'+unique+'"']); // undefined
console.log(MyArray [unique.toString()]); // undefined

The keys you tried there were 85481726, "85481726" (with double quotes), and 85481726 again. Note that you never tried '85481726' (with single quotes), which is the key you used originally. Since you didn't use the same key, you didn't get the value.

Either use consistent quotes, or (much better) don't use quotes at all. Don't worry about the array length being a large number, JavaScript arrays are inherently sparse. Adding an entry with a large index does not create several thousand undefined entries in front of it.

All of that being said, unless you need the "array-ness" of arrays, you can just use an object instead. Arrays are useful if you use their features; if you're not using their array features, just use an object.


More about the sparseness of arrays: Consider this code:

var a = [];
a[9] = "testing";
console.log(a.length); // 10

Although the length property is 10, the array has only one entry in it, at index 9. This is not just sophistry, it's the actual, technical truth. You can tell using in or hasOwnProperty:

console.log(a.hasOwnProperty(3)); // false
console.log("3" in a);            // false

When you try to retrieve an array element that doesn't exist, the result of that retrieval is undefined. But that doesn't mean there's an element there; there isn't. Just that trying to retrieve an element that doesn't exist returns undefined. You get the same thing if you try to retrieve any other property the object doesn't have:

var a = [];
a[9] = "testing";
console.log(a[0]);     // undefined
console.log(a[200]);   // undefined
console.log(a["foo"]); // undefined

Final note: All of this is true of the standard arrays created with [] or new Array(). In the next spec, JavaScript is gaining true arrays, created with constructors like Int32Array and such. Those are real arrays. (Many engines already have them.)

Sign up to request clarification or add additional context in comments.

Comments

1

If you are going to use an array that's mostly sparse, then use a Hash table instead.

eg, set your variable as follows:

ListUI_col_Orders = {};

Then your indexing will be a key, so you don't have to worry about all the interstitial elements taking up space.

5 Comments

Why? That's all standard JavaScript arrays are anyway, you don't gain anything.
Really? I thought it would have implemented hashes and arrays differently, as do most other languages. Although granted, this IS javascript... If you could point me to a reference, I'll do due diligence on this and delete my answer.
@ R: There's the specification (which is linked from my article above as well). ;-)
Skimming through it... don't see anything clearly stating this. Did a quick console test, and the results are as I expected. An initialization of x[2] (ignoring 0 & 1) creates elements 0 and 1 with null values. Likewise, using x[2] with a hash does not create the intermediate values. Maybe it's implementation dependent, but that's good enough for me. I think my answer is correct and I will keep it. Thank you though.
@ R: No, it's not implementation-dependent, and yes, the specification is clear about it. Don't skim, read. :-) The spec language is incredibly dense and hard to read, but it's there. Proof: jsbin.com/sumexahi/1 (source: jsbin.com/sumexahi/1/edit). JavaScript arrays, as the spec says in the first sentence of the relevant section, are just objects that give special treatment to a particular set of property names; have a magical length property; and are backed by Array.prototype. That's it.

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.