array like objects

Breton Slivka zen at zenpsycho.com
Mon Dec 14 15:21:38 PST 2009


On Tue, Dec 15, 2009 at 6:29 AM, Mike Samuel <mikesamuel at gmail.com> wrote:

> (3) If (!1), should future EcmaScript drafts define iteration order
> for arrays as index order and possibly recommend to array like host
> objects that the define iteration order similarly.


I would suggest that this change would be mostly useless to me in my
day to day work.  The fact that past ecmascripts made the mistake of
enumerating over properties that should not be enumerated over (such
as monkey patched functions) is a fact of life that spawned two
patterns:

1. The crockford iteration:
for(var i in o) {
    if(o.hasOwnProperty(i)){
       //iteration code
    }
}
2. The array-like iteration:
for(var i = 0; i<o.length; i++) {
    //iteration code
}

When I iterate over an array or array like, I want JUST the numbered
indexes and none of the named indexes. I cannot think of a pattern
that uses for( x in y) which can gaurantee that, and I can't figure
out how I would use it in day to day work.  The iteration code would
need to be prepared for either a numeric i, or a string i, so I
couldn't safely do arithmetic OR string operations on it without
deciding which I was dealing with first. Even if I did so, I can't
think of a situation where such code would be useful. not to mention,
would not changing the order break compatibility with existing
programs?

A far more useful direction for iteration is the generalization of the
forEach, map, and filter array extras. As others have pointed out,
there is an implicit contract in these methods. These are methods that
actually make programming easier, rather than just being useless
appendixes like some rigging of for-in iteration order would be. I
have no opinion on whether they should be static methods or not.

My suggestion would be that if an object can function as the "this"
argument within Array.prototype.slice, and slice returns a non empty
array, then it is array like, and should be acceptable within any of
the other array extras, as that's what I expect. This includes user
defined objects such as the jQuery object, host collections, the
arguments object, arrays from other frames, etc. This matches with
patterns that I use, patterns used in jquery, the pattern of calling
Array.prototype.slice on arguments objects, it renders moot the
trouble with arrays from external frames, and so on.

The only pitfall, which I've already pointed out, is that it also
includes strings, and may, if naively defined ( as I did earlier)
include functions, or objects in the style of {width:20, height:40:
length:60}. When I write templating functions, or dom tree walking
functions, I often need to distinguish between a host collection, an
array or array like, and a string, to decide whether I simply pass the
object on as is, or iterate over it. (is it singular or multiple in
nature?)

The fact is, javascript libraries, and programmers will use any
language construct they can grab a hold of to make reasonable
decisions that work within the program their writing. I'm not sure
what value there would be in TC-39 decreeing a pattern as blessed,
because programmers are just as likely to ignore it and just use what
works for them, today, right now, no matter how technically wrong it
is.

However, the discussion here has revealed one interesting thing: Both
ES3 and ES5 are inadequate for efficiently determining one particular
property of an object that would be useful in the accuracy of these
decisions. That is, it is difficult to determine whether an object has
numeric properties or not without iterating over [length] elements. If
there was some flag in an object that gets set on *insertion* of a
numeric property, a flag which is observable in some way from user
code, or something that gets observed by a built in isArrayLike, that
would, I believe, close this gap. Does it make sense to try and unset
the flag once it is set? I don't think that would be necessary.


More information about the es-discuss mailing list