Bug 62928

Summary: JavaScript for... in loses object order
Product: [Applications] konqueror Reporter: bht
Component: kjsAssignee: Konqueror Developers <konq-bugs>
Status: RESOLVED DUPLICATE    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: RedHat Enterprise Linux   
OS: Linux   
Latest Commit: Version Fixed In:

Description bht 2003-08-19 01:37:31 UTC
Version:            (using KDE KDE 3.1.1)
Installed from:    RedHat RPMs
OS:          Linux

<!--/*

Testcase for:

JavaScript for... in loses object order

Browser: Konqueror 3.1-12 Red Hat (Using KDE 3.1-10 Red Hat)

Submitted on 2002-08-19 at http://bugs.kde.org/wizard.cgi


How to reproduce:

- Open this file e.g. as index.html
- Click on button "Test"

Expected result: Object properties are listed in the same order
                 as they are added in the constructor.

Actual result:    Object properties are mixed up.

Comments:

This is critical because there must be at least one reliable order that
is not dependent on property names. If one wants a different order than
one can always use Array.sort().

All other major JavaScript capable browsers, i.e.
- Netscape 4
- Netscape 7 / Mozilla
- IE4...6 on Windows
- IE4...5 on Mac
do  preserve the order as exactly the same as the properties
were added to objects.

This is of great importance for object serialization into delimited
strings that, in case of serialised collections, must always have the
member count first otherwise they cannot be deserialized.

I think it is generally not difficult to understand that for GENERIC
serialisation and deserialisation, preserving the order of attributes
within Object is absolutely essential.

*/-->

<HTML>
<HEAD>
<TITLE>&qout;for..in..&qout; order lost</TITLE>
<SCRIPT>



// This is a constructor that creates a Model object from a string
// of values delimited by "|"
function Model(str){
    var attrs = str.split("|");
    var idx = 0;
    this.weight = attrs[idx++];
    this.size = attrs[idx++];
    this.color = attrs[idx++];
}// constr


// This is a generic function that serializes an object into a string
// of values delimited by "|"
function serialize(obj){
    var str = "";
    for(var attr in obj){
        str += obj[attr];
        str += "|";
    }// for
    return str;
}// function


function test(){
    // Create a Model object from a string of values delimited by "|"
    var model = new Model("5kg|1.5m|blue|");
    // Serialize this object
    var str = serialize(model, Model);
    // deserialize it
    var model = new Model(str);
    // Check if the object has kept all information including
    // the order of its properties, which is important for serialisation.
    if(model.weight == "5kg"
        && model.size == "1.5m"
        && model.color == "blue"){
        alert("Test succeeded");
    }// if
    else{
        alert("Test failed\nmodel.weight = " + model.weight
        + "\nmodel.size = " + model.size
        + "\nmodel.color = " + model.color);
    }// else
}// function

</SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT type = button value=Test onclick=test()>
</FORM>

</BODY>
</HTML>
Comment 1 Harri Porten 2003-10-05 17:09:20 UTC
The ordering of properties is implementation dependent (see the standard).
You shouldn't rely on it. If you want a fixed order do as you indicated above:
use sort().

We might unify ordering of properties on day but it has to be done carefully in
order not to decrease efficency.
Comment 2 bht 2003-10-05 20:57:52 UTC
Harri,

Thanks for examining this issue.

Unfortunately, the standard is painfully unhelpful in this particular case.

Please let me use a very relevant analogy from the SQL database domain:
If you are familiar with SQL database technology then you will recognise
that in this domain, things are standardised and handled correctly:

The SQL "SELECT * FROM MY_TABLE;" lists the contents of "MY_TABLE" in exactly
the same column order as the fields were defined in the data definition language
(DDL).

Even in the DDL itself, when you add a field to an existing table layout,
then it gets appended to the end of the layout, preserving the column order.

As you know, the ECMA standard was only created AFTER thwo fairly solid
JavaScript implementations existed for a significant period of browser history.

Today on the web, for commercial applications, and I hate to say that for
various other reasons, it is more practical to follow what Microsoft Internet
Explorer
and Netscape implement than what the standards are because these browsers
cover more than 90% of all browsers on the web today.

Because of this, it is not practical to penalise 90% of users with additional code
only to accommodate nascent, incomplete technology.

I am saying "incomplete" with some emphasis.

As you know, there are quite a few JavaScript commands in browsers that are not
part of the standard. However, all modern browsers today implement them because
without these, browsers would not be very useful at all:

window.open, document.write, window.setTimeout to name just a few.

Last not least I am referring to commercial browser based applications.
These applications have been released and they will generate thousands
of web sites. They definitely use the natural for ... in order
for critiacl purposes, in other words they do not function at all with a browser
that does not implement it.

I admire and to some extent share the enthusiasm of the KDE team for their product.
And I am very enthusiastic to support their work wherever I can.

That is why I am writing testcases early, to ensure that Konqueror gets on board.

Please fix this bug as soon as your resources permit it.
Comment 3 Harri Porten 2003-11-13 18:20:16 UTC

*** This bug has been marked as a duplicate of 28474 ***