FF3 Array Sort Bug?

H

Hamish Campbell

Hi all,

Does anyone understand how the 'default' sort algorithms for the major
browsers work? I was playing with .sort() after reading a previous
thread about array sorting. I was curious, because the ECMAScript
standard seems a bit silent on the issue, and array sorting seems to
be (more or less) implementation dependent. I could also be
misunderstanding how an array is enumerated with for-in - is the
GetValue property of an array specific to the implementation too?

Example:

<script language="javascript" type="text/javascript">
var data = new Array;
data[2] = 'integer (2)';
data[3] = 'integer (3)';
data[1] = 'integer (1)';

console.log("Before Sort");
for(var index in data)
console.log("index " + index + " was of type " + data[index]);

data.sort();

console.log("After Sort");
for(var index in data)
console.log("index " + index + " was of type " + data[index]);
</script>

FF3 and Chrome produce the output:

Before Sort
index 1 was of type integer (1)
index 2 was of type integer (2)
index 3 was of type integer (3)
After Sort
index 0 was of type integer (1)
index 1 was of type integer (2)
index 2 was of type integer (3)

IE8 produces the same result, but in the reverse order.

This is expected. However, if I add a string based key, such as below:

<script language="javascript" type="text/javascript">
var data = new Array;
data[2] = 'integer (2)';
data[3] = 'integer (3)';
data[1] = 'integer (1)';
data['a'] = 'string (a)';
</script>

I get the following output (FF3 3.0.10):

Before Sort
index 1 was of type integer (1)
index 2 was of type integer (2)
index 3 was of type integer (3)
index a was of type string (a)
After Sort
index 1 was of type integer (2)
index 2 was of type integer (3)
index a was of type string (a)
index 0 was of type integer (1)

Chrome (2.0.172.31) returns:

Before Sort
index a was of type string (a)
index 1 was of type integer (1)
index 2 was of type integer (2)
index 3 was of type integer (3)
After Sort
index a was of type string (a)
index 1 was of type integer (2)
index 2 was of type integer (3)
index 0 was of type integer (1)

IE8 returns:

Before Sort
index 2 was of type integer (2)
index 3 was of type integer (3)
index 1 was of type integer (1)
index a was of type string (a)
After Sort
index 2 was of type integer (3)
index 1 was of type integer (2)
index a was of type string (a)
index 0 was of type integer (1)

Thanks,
Hamish
 
H

Hamish Campbell

Hi all,

Does anyone understand how the 'default' sort algorithms for the major
browsers work? I was playing with .sort() after reading a previous
thread about array sorting. I was curious, because the ECMAScript
standard seems a bit silent on the issue, and array sorting seems to
be (more or less) implementation dependent. I could also be
misunderstanding how an array is enumerated with for-in - is the
GetValue property of an array specific to the implementation too?

Example:

<script language="javascript" type="text/javascript">
var data = new Array;
data[2] = 'integer (2)';
data[3] = 'integer (3)';
data[1] = 'integer (1)';

console.log("Before Sort");
for(var index in data)
   console.log("index " + index + " was of type " + data[index]);

data.sort();

console.log("After Sort");
for(var index in data)
   console.log("index " + index + " was of type " + data[index]);
</script>

FF3 and Chrome produce the output:

   Before Sort
   index 1 was of type integer (1)
   index 2 was of type integer (2)
   index 3 was of type integer (3)
   After Sort
   index 0 was of type integer (1)
   index 1 was of type integer (2)
   index 2 was of type integer (3)

IE8 produces the same result, but in the reverse order.

This is expected. However, if I add a string based key, such as below:

<script language="javascript" type="text/javascript">
var data = new Array;
data[2] = 'integer (2)';
data[3] = 'integer (3)';
data[1] = 'integer (1)';
data['a'] = 'string (a)';
</script>

I get the following output (FF3 3.0.10):

   Before Sort
   index 1 was of type integer (1)
   index 2 was of type integer (2)
   index 3 was of type integer (3)
   index a was of type string (a)
   After Sort
   index 1 was of type integer (2)
   index 2 was of type integer (3)
   index a was of type string (a)
   index 0 was of type integer (1)

Chrome (2.0.172.31) returns:

   Before Sort
   index a was of type string (a)
   index 1 was of type integer (1)
   index 2 was of type integer (2)
   index 3 was of type integer (3)
   After Sort
   index a was of type string (a)
   index 1 was of type integer (2)
   index 2 was of type integer (3)
   index 0 was of type integer (1)

IE8 returns:

   Before Sort
   index 2 was of type integer (2)
   index 3 was of type integer (3)
   index 1 was of type integer (1)
   index a was of type string (a)
   After Sort
   index 2 was of type integer (3)
   index 1 was of type integer (2)
   index a was of type string (a)
   index 0 was of type integer (1)

Thanks,
Hamish

(apologies - just realized the subject line was misleading - have
corrected)
 
T

Thomas 'PointedEars' Lahn

Hamish said:
Does anyone understand how the 'default' sort algorithms for the major
browsers work? I was playing with .sort() after reading a previous
thread about array sorting. I was curious, because the ECMAScript
standard seems a bit silent on the issue,and array sorting seems to
be (more or less) implementation dependent. I could also be
misunderstanding how an array is enumerated with for-in

Yes, your observations are based on two false premises.

First, that for-in iteration would be supposed to observe any order, and
would therefore be suitable to determine how an array is sorted; it is not,
as specified in the ECMAScript Language Specification, Edition 3 Final
[ES3F], section 12.6.4.

Second, that an ECMAScript Array object would work like a PHP array, or a
Python dictionary, and the like; it does not. Array objects are ECMAScript
objects and therefore they support the bracket property accessor. In
addition, Array objects encapsulate an array data structure by using its
properties with numeric name (in the range of unsigned 32-bit Integer) as
array elements. See [ES3F], section 15.4.
- is the GetValue property of an array specific to the implementation too?

Possible, but unlikely.
Example:
[...]
This is expected. However, if I add a string based key, such as below:

<script language="javascript" type="text/javascript">

The `language' attribute is deprecated since almost 10 years now, and was
never really necessary.
var data = new Array;
data[2] = 'integer (2)';
data[3] = 'integer (3)';
data[1] = 'integer (1)';
data['a'] = 'string (a)';

In this line you augment the newly constructed Array object with a property
named `a'. Since `a' is not an unsigned 32-bit Integer, that assignment
will _not_ add an element to the array. As a result, the value of
data.length remains 4 (indexes start at 0 [zero], the corresponding first
element of the array remains `undefined' here.)


HTH

PointedEars
___________
[ES3F] <https://developer.mozilla.org/en/JavaScript_Language_Resources>
 
G

Garrett Smith

Thomas said:
Hamish said:
Does anyone understand how the 'default' sort algorithms for the major
browsers work? I was playing with .sort() after reading a previous
thread about array sorting. I was curious, because the ECMAScript
standard seems a bit silent on the issue,and array sorting seems to
be (more or less) implementation dependent. I could also be
misunderstanding how an array is enumerated with for-in

Yes, your observations are based on two false premises.

First, that for-in iteration would be supposed to observe any order, and
would therefore be suitable to determine how an array is sorted; it is not,
as specified in the ECMAScript Language Specification, Edition 3 Final
[ES3F], section 12.6.4.

Second, that an ECMAScript Array object would work like a PHP array, or a
Python dictionary, and the like; it does not. Array objects are ECMAScript
objects and therefore they support the bracket property accessor. In
addition, Array objects encapsulate an array data structure by using its
properties with numeric name (in the range of unsigned 32-bit Integer) as
array elements. See [ES3F], section 15.4.
- is the GetValue property of an array specific to the implementation too?

Possible, but unlikely.
Example:
[...]
This is expected. However, if I add a string based key, such as below:

All properties are strings, or are converted to strings.

[...]
var data = new Array;
data[2] = 'integer (2)';
data[3] = 'integer (3)';
data[1] = 'integer (1)';
data['a'] = 'string (a)';

In this line you augment the newly constructed Array object with a property
named `a'. Since `a' is not an unsigned 32-bit Integer, that assignment
will _not_ add an element to the array. As a result, the value of
data.length remains 4 (indexes start at 0 [zero], the corresponding first
element of the array remains `undefined' here.)

The first element does not exist at all. There is no "0" property on
that array. The result of attempting to [[Get]] a "0" property will be
undefined.

"0" in data; // false.

Garrett
 
T

Thomas 'PointedEars' Lahn

Garrett said:
Thomas said:
Hamish said:
[...] However, if I add a string based key, such as below:

All properties are strings, or are converted to strings.

That wording is too imprecise to be not misleading. All property *names*
are strings. And when a bracket property accessor has a parameter that is
not a primitive string value, that parameter is converted to string (using
the internal ToString() algorithm, which in turn calls the toString() or
valueOf() method of the parameter converted to an object) for the purpose of
property access.
var data = new Array;
data[2] = 'integer (2)';
data[3] = 'integer (3)';
data[1] = 'integer (1)';
data['a'] = 'string (a)';
In this line you augment the newly constructed Array object with a property
named `a'. Since `a' is not an unsigned 32-bit Integer, that assignment
will _not_ add an element to the array. As a result, the value of
data.length remains 4 (indexes start at 0 [zero], the corresponding first
element of the array remains `undefined' here.)

The first element does not exist at all. There is no "0" property on
that array. The result of attempting to [[Get]] a "0" property will be
undefined.

That is what I meant.
"0" in data; // false.

True, however for all other intents and purposes the value of the property
with the name "0" can be considered to remain `undefined'. That said, it
should be noted that, in fact, the `length' property of an Array object does
not yield the number of elements in the array but the greatest index
available for new elements instead.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
[...] it should be noted that, in fact, the `length' property of an Array object does
not yield the number of elements in the array but the greatest index ^^^^^^^^^^^^^^^^^^^^^^
available for new elements instead.
^^^^^^^^^^^^^^^^^^^^^^^^^^
Argh, language, difficult thing. The greatest used index + 1.


PointedEars
 
E

Evertjan.

Thomas 'PointedEars' Lahn wrote on 10 jun 2009 in comp.lang.javascript:
Thomas said:
[...] it should be noted that, in fact, the `length' property of an
Array object does not yield the number of elements in the array but
the greatest index ^^^^^^^^^^^^^^^^^^^^^^
available for new elements instead.
^^^^^^^^^^^^^^^^^^^^^^^^^^
Argh, language, difficult thing. The greatest used index + 1.

Maybe Javascript is the GRAETEST difficult thing in clientside scripting,
but better look for the LARGEST index + 1.
 
H

Hamish Campbell

Hamish said:
Does anyone understand how the 'default' sort algorithms for the major
browsers work? I was playing with .sort() after reading a previous
thread about array sorting. I was curious, because the ECMAScript
standard seems a bit silent on the issue,and array sorting seems to
be (more or less) implementation dependent. I could also be
misunderstanding how an array is enumerated with for-in

Yes, your observations are based on two false premises.

First, that for-in iteration would be supposed to observe any order, and
would therefore be suitable to determine how an array is sorted; it is not,
as specified in the ECMAScript Language Specification, Edition 3 Final
[ES3F], section 12.6.4.

Second, that an ECMAScript Array object would work like a PHP array, or a
Python dictionary, and the like; it does not.  Array objects are ECMAScript
objects and therefore they support the bracket property accessor.  In
addition, Array objects encapsulate an array data structure by using its
properties with numeric name (in the range of unsigned 32-bit Integer) as
array elements.  See [ES3F], section 15.4.

*penny drops*. Ok, that makes a lot more sense. I read that section
but didn't quite take it in at the time :/
- is the GetValue property of an array specific to the implementation too?

Possible, but unlikely.
Example:
[...]
This is expected. However, if I add a string based key, such as below:
<script language="javascript" type="text/javascript">

The `language' attribute is deprecated since almost 10 years now, and was
never really necessary.

Yeah, old (bad) habit I need to lose. Validator always picks it up, so
you'd think I'd learn.
var data = new Array;
data[2] = 'integer (2)';
data[3] = 'integer (3)';
data[1] = 'integer (1)';
data['a'] = 'string (a)';

In this line you augment the newly constructed Array object with a property
named `a'.  Since `a' is not an unsigned 32-bit Integer, that assignment
will _not_ add an element to the array.  As a result, the value of
data.length remains 4 (indexes start at 0 [zero], the corresponding first
element of the array remains `undefined' here.)

HTH

PointedEars
___________
[ES3F] <https://developer.mozilla.org/en/JavaScript_Language_Resources>

Bookmarked.

Thanks, learned something today.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,001
Messages
2,570,255
Members
46,852
Latest member
CarlaDowle

Latest Threads

Top