Order of Key-Value pair ("associative arrays")

Discussion in 'Javascript' started by Abdullah Kauchali, May 25, 2004.

  1. Hi folks,

    Can one rely on the order of keys inserted into an associative Javascript
    array? For example:


    var o = new Object();

    o["first"] = "Adam";
    o["second"] = "Eve";
    o["third"] = "Cane";
    o["fourth"] = "Abel";

    ..
    ..
    ..

    //then

    for (var i in o){
    alert(i);
    }

    Is the order in this "for loop" *guaranteed* to be:
    first, second, third, fourth?

    Also, if the "third" key is deleted, is the order still guaranteed?

    I've tested this in IE and Firefox, and it seems to work. I'd be grateful
    for any links that indicate this in Javascript standards/specs.

    Many thanks & kind regards,

    Abdullah
     
    Abdullah Kauchali, May 25, 2004
    #1
    1. Advertising

  2. Abdullah Kauchali

    ZER0 Guest

    On Tue, 25 May 2004 12:35:50 +0200, Abdullah Kauchali wrote:

    [cut]
    > Is the order in this "for loop" *guaranteed* to be:
    > first, second, third, fourth?


    Unfortunately, not.
    Depend of the browser's implementation of this aspect of ECMAScript
    specifications.

    In IE,old Netscape versions, and Gecko based browsers, the order is
    "chronological".. But.. try with Opera.

    > for any links that indicate this in Javascript standards/specs.


    http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

    [for-in statement]
    "The mechanics of enumerating the properties (..) is
    implementation dependent. The order of enumeration is defined by the
    object. (..) "

    --
    ZER0://coder.gfxer.web-designer/

    ~ Come devo regolare la stampante laser per stordire?
    (How do I set a laser printer to stun?)

    on air ~ "Linkin Park - Somewhere I Belong (real song)"
     
    ZER0, May 25, 2004
    #2
    1. Advertising

  3. "ZER0" <> wrote in message
    > http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
    >
    > [for-in statement]
    > "The mechanics of enumerating the properties (..) is
    > implementation dependent. The order of enumeration is defined by the
    > object. (..) "



    Ho bummer! :(

    Thanks for that Zero.

    Now, how do I accomplish the following if the order is not guaranteed:

    1. Put objects within the "collection";
    2. Access each one according to the order in which they were put into the
    collection.

    So far, I have this:

    It seems to me that the most straight-forward answer would be to create
    another "collection" with index numbers beginning with 0 and then always
    incrementing for additions to the collections. Once a index/offset number
    is used, it cannot be reused.

    So, after some additions and deletions, I'll get something like:

    1, 2, 3, 7, 9, 11, 23

    if I wanted to add to this collection, the next one would be 24 and so on.

    Is that the most elegant solution?

    Kind regards

    Abdullah
     
    Abdullah Kauchali, May 25, 2004
    #3
  4. > Can one rely on the order of keys inserted into an associative Javascript
    > array? For example:
    >
    > var o = new Object();
    >
    > o["first"] = "Adam";
    > o["second"] = "Eve";
    > o["third"] = "Cane";
    > o["fourth"] = "Abel";


    No. The ECMAScript specification allows the contents of an object to be
    unordered. Most implementations do order the contents, but you should
    not rely on that.

    Also, the preferred way of initializing an object is with the object
    literal notation.

    var o = {first: "Adam", second: "Eve", third: "Cain",
    fourth: "Abel"};

    See http://www.JSON.org
     
    Douglas Crockford, May 25, 2004
    #4
  5. "ZER0" <> wrote in message
    > "chronological".. But.. try with Opera.


    Just tried it with Opera 7.50 and it seems to honour the order in which it
    was originally put in - the same as IE and Mozilla/FF.

    Almost there, but no official sanction from the specs! :(
     
    Abdullah Kauchali, May 25, 2004
    #5
  6. Abdullah Kauchali

    ZER0 Guest

    On Tue, 25 May 2004 15:43:45 +0200, Abdullah Kauchali wrote:

    > Just tried it with Opera 7.50 and it seems to honour the order in which it
    > was originally put in - the same as IE and Mozilla/FF.


    The last Opera I've seen was 7.0; and in that version the order was
    different.

    So, Now Opera seems use the same order of IE and Gecko.. Good news.

    > Almost there, but no official sanction from the specs! :(


    Yes, as I said is implementation dependent.

    --
    ZER0://coder.gfxer.web-designer/

    ~ Tutti quelli che credono nella psicocinesi, per favore alzino la mia
    mano.

    on air ~ "Avril Lavigne - Don't Tell Me"
     
    ZER0, May 25, 2004
    #6
  7. "Douglas Crockford" wrote in message

    >var o = {first: "Adam", second: "Eve", third: "Cain",
    > fourth: "Abel"};



    I don't think I can do that. The key/value pairs are unknown until runtime.

    Unless, of course, I am unaware of the way to initialise the way you mention
    for key/value pairs only known at runtime, then I'd be glad to learn how to
    do it.

    Kind regards

    Abdullah
     
    Abdullah Kauchali, May 25, 2004
    #7
  8. Abdullah Kauchali

    Grant Wagner Guest

    Abdullah Kauchali wrote:

    > "ZER0" <> wrote in message
    > > http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
    > >
    > > [for-in statement]
    > > "The mechanics of enumerating the properties (..) is
    > > implementation dependent. The order of enumeration is defined by the
    > > object. (..) "

    >
    > Ho bummer! :(
    >
    > Thanks for that Zero.
    >
    > Now, how do I accomplish the following if the order is not guaranteed:
    >
    > 1. Put objects within the "collection";
    > 2. Access each one according to the order in which they were put into the
    > collection.
    >
    > So far, I have this:
    >
    > It seems to me that the most straight-forward answer would be to create
    > another "collection" with index numbers beginning with 0 and then always
    > incrementing for additions to the collections. Once a index/offset number
    > is used, it cannot be reused.
    >
    > So, after some additions and deletions, I'll get something like:
    >
    > 1, 2, 3, 7, 9, 11, 23
    >
    > if I wanted to add to this collection, the next one would be 24 and so on.
    >
    > Is that the most elegant solution?
    >
    > Kind regards
    >
    > Abdullah


    That's pretty much what you do. You can wrap it in functions to make it easier
    to manage:

    function addToCollection(collection, collectionOrder, property, value) {
    collection[property] = value;
    collectionOrder.push(property);
    }

    function removeFromCollection(collection, collectionOrder, property) {
    collection[property] = null;
    for (var i = 0; i < collectionOrder.length; i++) {
    if (collectionOrder == property) {
    collectionOrder = null;
    break;
    }
    }
    }

    function dumpCollection(collection, collectionOrder) {
    var output = [];
    for (var i = 0; i < collectionOrder.length; i++) {
    if (collectionOrder != null) {
    output.push(collection[collectionOrder]);
    }
    }
    return output;
    }

    var o = new Object();
    var oOrder = new Array();

    addToCollection(o, oOrder, "first", "Adam");
    addToCollection(o, oOrder, "second", "Eve");
    addToCollection(o, oOrder, "third", "Cane");
    addToCollection(o, oOrder, "fourth", "Abel");
    removeFromCollection(o, oOrder, "second");
    addToCollection(o, oOrder, "fifth", "Noah");
    alert(dumpCollection(o, oOrder));

    If you want to get really fancy, you could write a "Collection" object that
    encapsulates all this functionality:

    function Collection() {
    var collection = {};
    var order = [];

    this.add = function(property, value) {
    if (!this.exists(property)) {
    collection[property] = value;
    order.push(property);
    }
    }
    this.remove = function(property) {
    collection[property] = null;
    for (var i = 0; i < order.length; i++) {
    if (order == property) {
    order = null;
    break;
    }
    }
    }
    this.toString = function() {
    var output = [];
    for (var i = 0; i < order.length; i++) {
    if (order != null) {
    output.push(collection[order]);
    }
    }
    return output;
    }
    this.getKeys = function() {
    var keys = [];
    for (var i = 0; i < order.length; i++) {
    if (order != null) {
    keys.push(order);
    }
    }
    return keys;
    }
    this.update = function(property, value) {
    if (value != null) {
    collection[property] = value;
    }
    for (var i = 0; i < order.length; i++) {
    if (order == property) {
    order = null;
    order.push(property);
    break;
    }
    }
    }
    this.exists = function(property) {
    return collection[property] != null;
    }
    }

    var myCollection = new Collection();
    myCollection.add("first", "Adam");
    myCollection.add("second", "Eve");
    myCollection.add("third", "Cane");
    myCollection.add("fourth", "Abel");
    myCollection.remove("second");
    myCollection.add("fifth", "Noah");
    alert(myCollection.toString());
    alert(myCollection.getKeys());
    myCollection.update("first");
    alert(myCollection.toString());
    alert(myCollection.exists("third"));
    alert(myCollection.exists("something"));

    The one thing you can't do with my code is actually store a null value in a
    collection entry. If you need to be able to do that, then you should use
    another object inside Collection to track if a collection entry actually
    contains a value or not.

    --
    | Grant Wagner <>

    * Client-side Javascript and Netscape 4 DOM Reference available at:
    *
    http://devedge.netscape.com/library/manuals/2000/javascript/1.3/reference/frames.html

    * Internet Explorer DOM Reference available at:
    *
    http://msdn.microsoft.com/workshop/author/dhtml/reference/dhtml_reference_entry.asp

    * Netscape 6/7 DOM Reference available at:
    * http://www.mozilla.org/docs/dom/domref/
    * Tips for upgrading JavaScript for Netscape 7 / Mozilla
    * http://www.mozilla.org/docs/web-developer/upgrade_2.html
     
    Grant Wagner, May 25, 2004
    #8
  9. "Grant Wagner" <> wrote in message

    <humbling code example snipped>

    OMG. Thank you so much. Beats the hell out of making the attempts on my
    own!

    Many thanks, once again,

    Kind regards

    Abdullah
     
    Abdullah Kauchali, May 25, 2004
    #9
  10. Abdullah Kauchali

    ZER0 Guest

    On Tue, 25 May 2004 17:38:49 GMT, Grant Wagner wrote:

    >
    > That's pretty much what you do. You can wrap it in functions to make it easier
    > to manage:

    [cut]
    > If you want to get really fancy, you could write a "Collection" object that
    > encapsulates all this functionality:


    An Additional note: This code on IE, works only for version 5.5 or major;
    because it use the push() array's method.

    --
    ZER0://coder.gfxer.web-designer/

    ~ You don't have to be crazy to be a webmaster. But it helps.
     
    ZER0, May 26, 2004
    #10
  11. Abdullah Kauchali

    Grant Wagner Guest

    ZER0 wrote:

    > On Tue, 25 May 2004 17:38:49 GMT, Grant Wagner wrote:
    >
    > > That's pretty much what you do. You can wrap it in functions to make it easier
    > > to manage:

    > [cut]
    > > If you want to get really fancy, you could write a "Collection" object that
    > > encapsulates all this functionality:

    >
    > An Additional note: This code on IE, works only for version 5.5 or major;
    > because it use the push() array's method.
    >
    > --
    > ZER0://coder.gfxer.web-designer/
    >
    > ~ You don't have to be crazy to be a webmaster. But it helps.


    if (typeof Array.prototype.push != 'function') {
    Array.prototype.push = function() {
    for (var i = 0 ; i < arguments.length ; i++) {
    this[this.length] = arguments;
    }
    }
    }

    --
    | Grant Wagner <>

    * Client-side Javascript and Netscape 4 DOM Reference available at:
    *
    http://devedge.netscape.com/library/manuals/2000/javascript/1.3/reference/frames.html

    * Internet Explorer DOM Reference available at:
    *
    http://msdn.microsoft.com/workshop/author/dhtml/reference/dhtml_reference_entry.asp
    * Netscape 6/7 DOM Reference available at:
    * http://www.mozilla.org/docs/dom/domref/
    * Tips for upgrading JavaScript for Netscape 7 / Mozilla
    * http://www.mozilla.org/docs/web-developer/upgrade_2.html
     
    Grant Wagner, May 26, 2004
    #11
  12. Abdullah Kauchali

    ZER0 Guest

    On Wed, 26 May 2004 13:21:55 GMT, Grant Wagner wrote:

    >> An Additional note: This code on IE, works only for version 5.5 or major;
    >> because it use the push() array's method.


    > if (typeof Array.prototype.push != 'function') {

    [cut]

    Better. :)

    --
    ZER0://coder.gfxer.web-designer/

    ~ Plagiarism is copying from one source;
    research is copying from two or more
    (Wilson Mizner)
     
    ZER0, May 26, 2004
    #12
  13. Abdullah Kauchali wrote:

    > Can one rely on the order of keys inserted into an associative Javascript
    > array? For example:


    JavaScript and other ECMAScript implementations have no built-in
    concept of associative arrays.

    > var o = new Object();
    >
    > o["first"] = "Adam";
    > o["second"] = "Eve";
    > o["third"] = "Cane";
    > o["fourth"] = "Abel";


    That is an Object object on which alphabetic properties are added, not
    an array. Try o.length or o.push(), neither is present or works, while
    o.first, o.second aso. work. (If properties are identifiers, they can
    be accessed both with the square bracket and the dot accessor.)

    Using Mozilla/5.0 and a for-in-loop, properties are iterated in the
    order of assignment, but there is no standard that specifies that.

    Additional note: Even

    var a = new Array();
    a[0] = 42;
    a["foo"] = "bar";

    creates an array with *one* element, not two:

    alert(a.length); // 1

    var s = "";
    for (var i in a)
    {
    s += i + " == " + a + "\n";
    }
    alert(s);


    PointedEars
     
    Thomas 'PointedEars' Lahn, May 30, 2004
    #13
  14. In article <>, Thomas 'PointedEars' Lahn
    <> writes
    >Abdullah Kauchali wrote:
    >
    >> Can one rely on the order of keys inserted into an associative Javascript
    >> array? For example:

    >
    >JavaScript and other ECMAScript implementations have no built-in
    >concept of associative arrays.

    <snip>

    It's the other way round. Every ECMAScript object is an associative
    array.

    Even Array objects are associative arrays. It's a syntax fudge that
    makes Array objects look, almost, like the arrays in other languages
    with their numeric indexes.

    John
    --
    John Harris
     
    John G Harris, May 30, 2004
    #14
  15. John G Harris <> writes:

    > It's the other way round. Every ECMAScript object is an associative
    > array.


    .... where "associative array" is just mumbo-jumbo for a mapping from
    something to something. I believe the name comes from Perl, although
    they could have taken it from somewhere else. It is really a misnomer,
    as it has nothing to do with "real" arrays.

    In, e.g., Java, I would never say "associative array". I'd just say
    "Map".

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, May 30, 2004
    #15
  16. In article <>, Lasse Reichstein Nielsen
    <> writes
    >John G Harris <> writes:
    >
    >> It's the other way round. Every ECMAScript object is an associative
    >> array.

    >
    >... where "associative array" is just mumbo-jumbo for a mapping from
    >something to something. I believe the name comes from Perl, although
    >they could have taken it from somewhere else. It is really a misnomer,
    >as it has nothing to do with "real" arrays.


    Back in the 1960s a lot of people got very excited about associative
    memory. It was, at last, possible to build one with less than a roomful
    of electronics. As it happens its most common use these days is in
    memory caches. These are buried inside processor chips and so are not
    very visible to users.

    An ordinary array is built from ordinary memory. You put in a relative
    address and a value comes back very, very quickly.

    An associative array is built from associative memory. You put in a key
    and a value comes back also very, very quickly ... if you can afford to
    use a million or so transistors. It's a lot slower if you have to use
    software to do it.

    Altogether, "associative array" is a perfectly respectable technical
    term that goes back a long way. It's wrong to complain if someone uses
    it.

    >In, e.g., Java, I would never say "associative array". I'd just say
    >"Map".


    In Java, what have Map and Dictionary got in common? They are both
    associative arrays. It's not very clear if you have to say that one is a
    Map and so is the other. And in C++ you can use array syntax, a, to
    get at the values.

    John
    --
    John Harris
     
    John G Harris, Jun 1, 2004
    #16
  17. Lasse Reichstein Nielsen wrote:

    > John G Harris <> writes:
    >> It's the other way round. Every ECMAScript object is an associative
    >> array.

    >
    > ... where "associative array" is just mumbo-jumbo for a mapping from
    > something to something. I believe the name comes from Perl, although
    > they could have taken it from somewhere else. It is really a misnomer,
    > as it has nothing to do with "real" arrays.
    >
    > In, e.g., Java, I would never say "associative array". I'd just say
    > "Map".


    Full ACK. To me, an "array" in computer science and thus programming is
    an *ordered* data structure (AIUI an "array" outside of computer science
    has the property of order as well), composed of *elements*. That means,
    one can access element #x or append elements at the end of to the array
    directly, without iteration.

    With a simple non-Array[1] ECMAScript object there are no such means
    available. You cannot access property #x unless you indexed it before
    and you cannot obtain the number of properties until you iterated the
    object using a for-in-loop. And even then you cannot tell for sure that
    these are all properties of the object (which would be then elements of
    the "associative array" if you like call them so) because some may have
    the NonEnum flag set and thus do not occur during iteration but yet are
    present. And single properties can be read-only. I don't know of any
    implementation that calls itself an "array" and that allows that kind
    of data hiding and level of data integrity protection regarding the
    elements of that "array".

    With an Array[1] ECMAScript object there is a distinction between array
    elements and object properties (as already shown). Array elements can be
    refered to as object properties with a(n) (numeric) index, but not all
    properties of an Array (object) are elements of the array (data structure)
    it encapsules.

    In contrast, in PHP for example, there are what I would consider associative
    arrays or maps. If you do

    $a = array();
    $a['foo'] = 'bar';

    or

    $a = array(
    'foo' => 'bar'
    );

    You can access $a['foo'] with $a[0] as well because it is the first
    element appended to the array. (Look how the "=>" operator tells
    of the mapping that is done.)

    Achieving that in ECMAScript and implementations requires another data
    structure similar to Array objects, which I refer to as a "collection",
    as specified for example with the HTMLCollection interface of the W3C
    DOM.


    PointedEars
    ___________
    [1] Note the character case!
     
    Thomas 'PointedEars' Lahn, Jun 2, 2004
    #17
  18. Abdullah Kauchali

    Grant Wagner Guest

    John G Harris wrote:

    > In article <>, Thomas 'PointedEars' Lahn
    > <> writes
    > >Abdullah Kauchali wrote:
    > >
    > >> Can one rely on the order of keys inserted into an associative Javascript
    > >> array? For example:

    > >
    > >JavaScript and other ECMAScript implementations have no built-in
    > >concept of associative arrays.

    > <snip>
    >
    > It's the other way round. Every ECMAScript object is an associative
    > array.


    No, every ECMAScript object is an object that can have properties which can be
    accessed using dot notation (theObject.theProperty), or "array" notation
    (theObject[theProperty]).

    > Even Array objects are associative arrays. It's a syntax fudge that
    > makes Array objects look, almost, like the arrays in other languages
    > with their numeric indexes.


    No, an Array object is a special object that represents an array. Array objects
    are "magical" (as is the Location object for a similar reason) because setting
    the value of an array index updates properties within the object, something that
    is not possible with other objects in an ECMA-262 compliant way. The closest you
    could get would be to use watch()/unwatch() in Netscape to monitor the updating
    of a property and act on it to update another property:

    var myArray = new Object();
    myArray.blahHandler = function() {
    alert('blah changed');
    }
    myArray.watch('blah', myArray.blahHandler);
    myArray.blah = 1;

    But even this doesn't approximate the behavior of the Array object, where the
    updating of an arbitrary "associative array" key that is an integer updates the
    length property of the object. Of course, one could argue that length isn't
    updated immediately, but instead returns a "count" of the number of properties
    attached to the Array object, but in that case, Array would still be "magical",
    with .length acting as a method call without "()" (and it seems pretty obvious
    from speed tests that .length doesn't actually execute any code to "count" the
    number of entries but is, at it appears to be, a simple property containing a
    value).

    By the way, Location is "magical" because it behaves in a way that is impossible
    if it were a normal object When you do window.location.href =
    'http://www.yahoo.com'; and window.location = 'http://www.yahoo.com'; and they
    result in the same action, it would be like expecting:

    var location = new Object();
    location.href = 'http://www.yahoo.com';

    and

    var location = new Object();
    location = 'http://www.yahoo.com';

    to have the same outcome.

    --
    | Grant Wagner <>

    * Client-side Javascript and Netscape 4 DOM Reference available at:
    *
    http://devedge.netscape.com/library/manuals/2000/javascript/1.3/reference/frames.html

    * Internet Explorer DOM Reference available at:
    *
    http://msdn.microsoft.com/workshop/author/dhtml/reference/dhtml_reference_entry.asp

    * Netscape 6/7 DOM Reference available at:
    * http://www.mozilla.org/docs/dom/domref/
    * Tips for upgrading JavaScript for Netscape 7 / Mozilla
    * http://www.mozilla.org/docs/web-developer/upgrade_2.html
     
    Grant Wagner, Jun 4, 2004
    #18
  19. Grant Wagner <> writes:

    > By the way, Location is "magical" because it behaves in a way that is impossible
    > if it were a normal object When you do window.location.href =
    > 'http://www.yahoo.com'; and window.location = 'http://www.yahoo.com'; and they
    > result in the same action, it would be like expecting:


    <nitpick>
    Technically, it would be both the location object and the window
    object that are magical.

    In both cases, assigning to a property will have a different effect
    than the expected one. For the location object, assigning to the
    "href" property changes the page's location, which is quite a side
    effect. For the window object, assigning to the "location" property
    doesn't change its value, but changes "location.href" instead.

    </nitpick>
    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Jun 4, 2004
    #19
  20. Abdullah Kauchali

    rh Guest

    Grant Wagner wrote:
    > John G Harris wrote:
    >

    <snip>
    > > It's the other way round. Every ECMAScript object is an associative
    > > array.

    >
    > No, every ECMAScript object is an object that can have properties which can be
    > accessed using dot notation (theObject.theProperty), or "array" notation
    > (theObject[theProperty]).
    >


    The original statement is correct. The accessor syntax, while being
    important, doesn't change the fundamental (logical) nature of the
    object.

    > > Even Array objects are associative arrays. It's a syntax fudge that
    > > makes Array objects look, almost, like the arrays in other languages
    > > with their numeric indexes.

    >
    > No, an Array object is a special object that represents an array. Array objects
    > are "magical" (as is the Location object for a similar reason) because setting
    > the value of an array index updates properties within the object, something that
    > is not possible with other objects in an ECMA-262 compliant way. The closest you
    > could get would be to use watch()/unwatch() in Netscape to monitor the updating
    > of a property and act on it to update another property:
    >


    Again, the original statement is correct.

    Array objects have a special "length" property, and some special
    methods (notably sort) that provide further array manipulation
    functionality within the language that distinquish them from standard
    objects. Nonetheless, there is no access to the underlying structure
    except through the standard object accessors. Therefore, regardless of
    any particular implementation, Array objects remain entirely
    associative in nature within the language.

    <snip>

    > By the way, Location is "magical" because it behaves in a way that is impossible
    > if it were a normal object.


    Yes, but host objects are outside ECMA-262, and there's all kinds of
    "magic" once you step out there. :)

    ../rh
     
    rh, Jun 5, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. sam
    Replies:
    1
    Views:
    677
    Gianni Mariani
    May 1, 2005
  2. Replies:
    1
    Views:
    580
    Daniel Pitts
    Nov 16, 2007
  3. Rui Maciel
    Replies:
    2
    Views:
    3,122
    AndrewDover
    Dec 1, 2009
  4. D. Krmpotic
    Replies:
    3
    Views:
    108
    D. Krmpotic
    Mar 23, 2007
  5. shashi
    Replies:
    17
    Views:
    437
    Guest
    Apr 13, 2006
Loading...

Share This Page