ES3 quasi incompatibilities

Garrett Smith dhtmlkitchen at
Sun Nov 11 18:01:37 PST 2007

Function findDuplicate is more like "mark duplicates". The side effect
is that it adds a __marker property to each object. As it stands, this
function can not be called more than once. The second call might be
passed a different array, but containing one of those objects that had
the __marker left over. Calling delete in a second loop would make the
algorithm 2n (best time). But this is not entirely safe; calling
delete on a Host object or window property will throw errors in
JScript env; and the property will still be there. So you can set
__marker = false, but then you've got a 2N algorithm that leaks a
"__marker" to objects in the program.

if (map[array[i]])
// array[i].toString() returns a property name that exists in the
prototype chain of map (such as "toString").


However, relying on toString in the second part is still unsafe.

findDuplicate([1, "1", !window, "false", new Date()+'', new Date()+'']);

What is really going into this Array?

I think I see the intent, but the function is easily breakable, even
if fixed to have a second loop to set marker to null when done; and
including the hasOwnProperty fix.

Interop might be an issue, but the code is broken even in ES3.

JavaScript does not provide basic functionality for unique collections.

Consider a case where we have an array-like collection of objects and
we want to exclude duplicates. Not uncommon at all.

This could be a shopping cart of unique items (properties), a list of
attendees, a ledger of customers, a merge of n number of Lists,
containing top-scoring players
We want a unique collection.

Using SortedSet:
// lis1, lis2 and lis3 are NodeList of LI, in Abstract View.

function compareFn(a, b) {
  return getScore(a) - getScore(b);

var players:Set = new SortedSet( compareFn );

var top10:Set = new Set(players);

Pros: fast, explicit

What's missing from ES4:
Set, SortedSet

Using Array:
// Copy of array-like, as array, w/o duplicates.
var players = Array.concat(lis1, lis2).concat(lis3).unique();
var top10 = players.toArray();
top10.length = 10;
Pros: compact
1) probably not as efficient (using quicksort)
2) slightly less explicit than the SortedSet example

What's missing from ES4:
Array.prototype.toArray( arrayLike ) (also as Array.toArray(arrayLike))

ES3 concat and splice are the only way to obtain a copy of an array.
These are not explicit uses, but workarounds for a missing arraycopy

I don't know how this problem could be solved with a Map. Doesn't feel
natural here. Here's my best shot at it:

var players = new Map<Object,Object>();

// Add all the players from each list into the players Map.
for(var i = 0; i < lis1.length; i++) {
    players.add(lis1[i], null);
for(var i = 0; i < lis2.length; i++) {
    players.add(lis2[i], null);
for(var i = 0; i < lis3.length; i++) {
    players.add(lis3[i], null);

var keys = map.getKeys();
var newPlayers = Array.toArray(keys);
newPlayers.length = 10;

1) not very straightforward or intuitive; not explicit
2) Verbose, requires two collections and a for loop.
3) Not efficient

What's missing:
Array.toArray( arraylike );

On Nov 9, 2007 10:00 AM, Lars Hansen <lhansen at> wrote:
> Map and intrinsic::hashcode are your friends, indeed.  Cleaner solution,
> too.
> <rambling>
> For non-dynamic classes you can still use meta::set and meta::get to allow
> for
> limited applications like this.  I keep thinking that there are use cases
> for
> global meta::get and meta::set functions, so just like operator overloading
> can be done by extending global, generic functions a la intrinsic::+, it
> ought to
> be possible to hook into catchalls on the global level, using generic
> functions.
> class C { ... } // not dynamic
> meta generic function get(c: C, name) {
>     if (name == "__marker")
>        ...
>     else
>        return nextMethod()
> }
> meta generic function set(c: C, name, val) {
>     if (name == "__marker")
>         ...
>     else
>         nextMethod()
> }
> </rambling>
> --lars
>  ________________________________
>  From: es4-discuss-bounces at
> [mailto:es4-discuss-bounces at] On Behalf Of Kris Zyp
> Sent: 9. november 2007 09:20
> To: es4-discuss at
> Subject: ES3 quasi incompatibilities
> > or whether ES4 precludes the use of current ES3 AOP patterns and how
> > that might be solved.  Among other things.)
> ES3 AOP is in a class of patterns that is not strictly incompatible as ES3
> code alone won't break, but ES3 code would no longer behave as expected when
> interacting with ES4 code. AOP and other patterns in ES3 rely on the ability
> to add or modify properties on any object. Another example that should be
> noted is the O(n) algorithm for duplicate item and cyclic reference
> detection. For example:
> function findDuplicate(array){
>  var map={};
>  for (var i = 0; i < array.length; i++) {
>   if (typeof array[i] == 'object') {
>    if (array[i].__marker)
>     alert('found duplicate');
>    array[i].__marker = true;
>   }
>   else {
>    if (map[array[i]])
>     alert('found duplicate');
>    map[array[i]] = true;  }
>  }
> }
> This algorithm will fail if an array of objects is passed in that includes
> instances of non-dynamic (default for user created) classes. Temporarily
> marking objects with dynamic properties is the only way I am aware of to
> create O(n) algorithms in ES3 to detect duplicates and cyclic references.
> I don't think there is anything that can be done about this, it is just a
> result of static classes. Code written for ES4 can use maps (I think anyway)
> to solve this problem. This has probably already been discussed, but I just
> wanted to make sure it was noted.
> Kris
> _______________________________________________
> Es4-discuss mailing list
> Es4-discuss at

Programming is a collaborative art.

More information about the Es4-discuss mailing list