I believe it is very very important that the ECMAScript standard specify that
when a new Object
is created, for..in iteration traverses properties in the order they are added, regardless of
whether the properties are numeric or not.
The primary reason is that I think it makes ECMAScript a much more expressive and usable
language, and results in better performance in real-world applications.
Secondarily, the fact that the Chrome browser has deviated from this de-facto standard is
creating a small crisis for site owners and web application developers, and it will get much
much worse if any other browser vendors follow suit.
This seems to have been most recently discussed in 2009 with inconclusive
results.
https://mail.mozilla.org/htdig/es-discuss/2009-October/010060.html
I have summarized the argument for this feature below - this argument has swayed others who
were initially opposed.
I'm hoping we can get quick consensus that *specifically Object iteration order* should be
preserved, without getting too bogged down in the details of specifying exactly what happens
for Arrays, prototype chains, etc. Major stakeholder agreement on this one aspect should be
enough to prevent any other vendors from shipping browsers that break sites, and get the Chrome
bug for this re-instated.
== Expressiveness and Performance argument
A very common use case where order preservation is desirable is providing the
set of options
for a drop-down list in JavaScript. Essentially all Ajax widget kits have such
an API, and
usage is generally:
selectControl.setOptions({
storedValue1 : "displayValue1",
storedValue2 : "displayValue2",
storedValue3 : "displayValue3"
})
Here are some examples of what alternatives might look like - all of them are
far, far worse:
#1 Parallel arrays:
selectControl.setOptions(
["storedValue1",
"storedValue2",
"storedValue3"],
["displayValue1",
"displayValue2",
"displayValue3"]
})
- this is awkward and unnatural, and doesn't correspond to how a list of
options is specified
in HTML
- involves *double* the number of allocations / GC-tracked objects (6 strings
and 2 Arrays
vs one Object and 3 Strings - slots don't GC)
- replacing a key/value pair requires a linear (0(n)) search unless secondary
indexing
approaches are used, which requires yet more allocation both to build and
maintain the index,
as well as a level of sophistication not typical for a scripting language user
#2 Array of Objects
selectControl.setOptions([
{value: "storedValue1", text: "displayValue1"},
{value: "storedValue2", text: "displayValue2"},
{value: "storedValue3", text: "displayValue3"}
]);
- verbose and redundant code - reiterates "value" and "text" once per entry
- much worse Object allocation than #1 (which was already bad): one Object + 2
Strings per
property
- same linear search / extra allocation / developer sophistication issue as #1
#3 Array of Arrays
selectControl.setOptions([
["storedValue1", "displayValue1"],
["storedValue2", "displayValue2"],
["storedValue3", "displayValue3"]
]);
- verbose, finger-spraining punctuation density
- much worse Object allocation than #1 (which was already bad): one Array + 2
Strings per
property
- same linear search / extra allocation / developer sophistication issue as #1
In a nutshell, dropping order preservation results in:
1. less expressive code
2. more bytes on the wire (both in code-as-such and JSON)
3. degraded application performance via increased allocations and the overhead
of implementing
order-preserving behavior in JavaScript
== Historical behavior argument
All browsers that have ever had non-negligible market share have implemented
order-preserving
Objects - until Chrome 6.
Like many universally consistent, obviously beneficial behaviors, many
developers relied on it
assuming eventual standardization.
Thousands of sites and applications are broken by Chrome's decision to drop the
order-preserving behavior. There is a bug against Chrome's V8 engine
(currently marked
"WorkingAsIntended"):
http://code.google.com/p/v8/issues/detail?id=164
People can "star" issues to be notified of changes in status or discussion.
This issue has by
far more stars than the most-starred Feature Request (E4X support), more than
double the stars
of the runner-up, and more stars than roughly the top 20 confirmed bugs
combined.
And this does not consider all the stars on other versions of this issue that
were closed as
duplicates.
Various arguments have gone back and forth on whether Chrome should fix this
bug without
waiting for standardization, but not a single person has indicated that they
would prefer that
Object does not preserve order.
In a nutshell, there is overwhelming support for adding this behavior to the
standard, and
still time to avoid all the wasted effort of changing all these sites and
applications. Very
few non-order-preserving browsers exist in wild, and the behavior is limited to
browsers that
are updated very frequently or even automatically.
== Objections and counter-arguments
1. Array for..in iteration order has always been inconsistent across browsers
Yes, this is true. I am proposing only that Object preserves insertion order,
not Array.
No developers or sites rely on Array for..in iteration order, since it was
never consistent.
If Array for..in iteration continues to be unordered, any developer that cares
about the tiny
performance difference can use an Array to store non-numeric property/value
pairs.
2. Not preserving insertion order allows JavaScript to run faster
It can't be a very large optimization, since Safari and Firefox continue to
challenge Chrome's
performance while maintaining in-order iteration. And if it's only a small
optimization, then
obviously it's completely dwarfed by the application-level penalties incurred
re-implementing
this key behavior in JavaScript.
3. It's good enough to preserve order for non-numeric keys only
This is an abysmal compromise, with the worst traits of each alternative. It requires browser
vendors to implement order preservation, such that we don't get the minor optimization that's
possible from not preserving order at all. At the same time, it requires that applications and
frameworks deal with lack of order for numeric keys, which are very common: in the use case of
mapping stored to displayed values, stored values are very often numeric.
It's also just bad design. It surprising and counter-intuitive that numeric keys are treated
differently from non-numeric. The reality is that an implementation detail of Array is
bleeding through to Object.
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss