JavaScript Associative Arrays #
There seems to be some confusion regarding associative arrays in JavaScript (i.e. doing searches on the matter turns up many pages giving wrong information). First of all, these arrays (which act as hash tables) have nothing to do with the built-in Array
object. They simply rely on the fact that object.property
is the same as object["property"]
. This means that the length
property is not used, nor do any Array
methods (such as join
) do anything. In fact, it is better to create the associative array using the generic Object()
constructor to make this clearer.
The way to iterate over the items in an associate array is to use the for (value in array)
construct, allowing you to access each item's value via array[value]
. It appears that the order in which properties (i.e. items) are traversed is implementation dependent. The ECMAScript specification is pretty vague on the matter, saying (in section 12.6.4) "Get name of the next property of [the object] that doesn't have the DontEnum attribute. If there is no such property, go to [the end]". Firefox, Safari and MSIE appear to traverse items in the order in which they were inserted, while KHTML (within KDE 3.1) and Opera (at least through 7.54) use a seemingly random order that presumably reflects their respective hashtable implementations.
The iteration order can be tested using a very simple code snippet such as this (click here to run it):
var items = {"dioxanes": 0, "shunning": 1, "plowed": 2, "hoodlumism": 3, "cull": 4, "learnings": 5, "transmutes": 6, "cornels": 7, "undergrowths": 8, "hobble": 9, "peplumed": 10, "fluffily": 11, "leadoff": 12, "dilemmas": 13, "firers": 14, "farmworks": 15, "anterior": 16, "flagpole": 17}; listString = ""; for (var word in items) listString += items[word] + ", "; alert(listString);
If the list of numbers appears in ascending order, then the browser preserves the insertion order. If you are in fact looking to traverse the object's properties in the order they were inserted in, regardless of browser implementation, you'll have to create a (possibly double) linked list that you can use to jump from object to object.
23 Comments
I had read all those other links from google and I was wondering why sort() and join() didn't work!
I can't believe so many people has such a false impression of associative arrays in Javascript. You are the man!
-Adeh
I am wondering why the following snippet would not work as I expect:
function OnClick(aName) {
var map = {aName : true};
for (var key in map)
alert(key + " : " + map[key]);
}
...
OnClick('a string');
...
This will assign a mapping like:
'aName' : true
instead of:
'a string' : true
Is there a solution to force Javascript to intepret aName as a string object, instead of the string itself?
map[aName] = true;
I have been a contributor to some of the "confusion regarding associative arrays in JavaScript" in an article on my site, which was part of a series published in print. At the time of writing I had my reasons for not mentioning that associate arrays do not have to be (and in fact probably shouldn't be) Array() type objects. However I agree entirely with your comments and in the interests of accuracy and clarity I have altered my page accordingy.
Cheers,
Trevor.
I would like to do the following:
var some_value=10;
var items = {"dioxanes": 0, "shunning": 1, "plowed": some_value};
I understand that the concept of associatvie array is fairly new to me, so it's maybe something simple that I'm missing.
thanks.
//----
var nantoka = new Object();
nantoka['cheese'] = 'Camembert';
nantoka['cartoon'] = 'Danger Mouse';
nantoka['cheese'] = null;
//----
Then the key/property of 'cheese' still remains (it simply equals NULL). Er...I guess what I want to do is to remove a property from an object (renaming it would also be good). Any advice/ideas?
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator
The mechanics of enumerating the properties [...] is implementation dependent. The order
of enumeration is defined by the object. Properties of the object being enumerated may be deleted during enumeration. If a property that has not yet been visited during enumeration is deleted, then it will not be visited. If new properties are added to the object being enumerated during enumeration, the newly added properties are not guaranteed to be visited in the active enumeration."
"toString". Any ideas?
for (var x in { toString: "pants" }) { alert( x ); }
(does not alert!)
>"toString". Any ideas?
>
>for (var x in { toString: "pants" }) { alert( x ); }
>(does not alert!)
No it's not broken and you can already find the solution on this page. Have a look at kemal's post.
but just for you, here it goes.
try this:
-----------
var assoArray = {toString: "pants"};
for (var x in assoArray) {alert(assoArray[x]);}
-----------
The way I see it (and please correct me if I'm wrong, I'm just speculating here) is that the variable x has nothing to do with the associative array. It's temporaly used to hold a string. You could look at it like this.
-----------
var assoArray = {toString: "pants"};
var x = "toString";
alert( assoArray[x] );
// The for(...) merely simplifies your life by dynamically associating the key-String to a variable and let you loop through the array. So look at 'x' as a string and not a reference to an element in the array as some other languages do.
-----------
that is bad news. Basically it just means that assoc arrays don't exist in javascript.
You might wonder what the difference is with an object with properties. Well performance wise, i have always heard property lookups are slow, and array lookups are fast.
cheers for the info
Well, consider the differences. A numeric array is directly linked to a memory map. Essentially, an associative array (or object) must search for its index in a table, then match it to a memory map. Whether you use an object, or you had associative arrays, you'd pretty much suffer in terms of performance there.
If performance is a big issue, use numeric arrays and keep documentation of a table match. The associative arrays just clean it up and do it for you.
This article was very informative for me, just because I was desesperate to find something about this issue. I´m curious to know how would be the notation of a bi-dimensional associative array in javascript. Could you show us how that can be???
Thank you and congratulations.
groups= new Array(0:Array(ID:'1',name:'first users',type:'users',creatorid:'203',creationdate:'1969-12-31 18:32:49',vis:'all',active:'1'),1:Array(ID:'2',name:'2nd users',type:'users',creatorid:'203',creationdate:'1969-12-31 18:32:49',vis:'all',active:'1'));
This doesn't seem to work. What else could I try?
myk
groups= {0: {ID:'1',name:'first users',type:'users',creatorid:'203',creationdate:'1969-12-31 18:32:49',vis:'all',active:'1'},1: {ID:'2',name:'2nd users',type:'users',creatorid:'203',creationdate:'1969-12-31 18:32:49',vis:'all',active:'1'}};
"Second, in ES4 the local enumeration order—the order in which properties of any one object in the
prototype chain is enumerated—is defined to be the order of insertion of those properties into that object.
Objects in the prototype chain must be visited in order, starting with the object that is the operand of the
for-in statement."
Thanks, you have made the world a favour!
I feel so dumb now for thinking an "associative array" was an array rather than a hash map.. doh!
Post a Comment