array like objects

Breton Slivka zen at zenpsycho.com
Mon Dec 14 16:15:10 PST 2009


On Tue, Dec 15, 2009 at 10:34 AM, Mike Samuel <mikesamuel at gmail.com> wrote:
> 2009/12/14 Breton Slivka <zen at zenpsycho.com>:
>> 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
>> }
>
> Does the performance of this on large sparse arrays pose problems for
> you in your day to day work?
> E.g. for (o = new Array(1e100)).
>

No it does not. While I know that large sparse arrays are possible, I
do not encounter them very often. The only time I've used a sparse
array is in a representation of a timeline, where I did not expect to
visit N indexes in greater than linear time. I would not consider this
"large" on the order of your example, though. I have never encountered
anything like that. My performance expectations are about the length
of the array, not how many elements are properly stored in it. I lie a
little bit here, there is one situation where I expect greater than
linear time: Serializing the timeline into JSON, I convert the sparse
array representation to an "array like" object representation before
serializing (to save space). In this case I explicitly use for/in
without identifying the type of the object first. I already have a
reasonable assurance about what it's going to be since I created the
object myself, it will either be an array, or undefined.

I will concede though, a way to efficiently iterate over a sparse
array in numeric order might be useful in some cases. I suggest the
forEach (and other) array methods for this though. The efficiency and
implementation of that does not have to be visible to the user, as
long as the interface remains the same, and does not need to involve
the ecmascript committee.



> Do you use jquery in day to day work?  I ask because that's one
> library that already seems to dynamically switch between the two.
>
>

Yes I do use jquery. I'm unsure about what you're referring to here
when you say "the two" though.



>
> Can you think of any existing programs that rely on the current
> (undefined but something like insertion order) order for arrays?
>
>
No I can't. I only know that standardising the order of iteration for
objects was brought up as a compatiblity issue during the ES4/ES5
standardization process, since all popular interpreters behave in the
same way. It would seem silly to me to then change the order after all
that fuss.

>
>> 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
>
> I think basing the definition on what Array.prototype.slice does is a
> decent criterion.
>
>> 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
>
> Only if those collections are not empty.  Calling slice on an empty
> array obviously returns an empty array which would fail your test
> above.
>

I'm not married to the nonempty criterion. What I mean here is to
exclude objects like {width:10, height:10, length:10}, or function
objects.  The non empty criterion is simply a heuristic, a naive
solution to this tricky logic problem. But the empty set is still a
set after all. I am open to better solutions, and I don't even mind
considering such an object array like. I just thought I would try, out
of consideration of the arguments of other posters.

>> 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.
>
> There are far fewer Javascript library writers than Javascript
> programmers so I'm not convinced that it's too large an audience to
> talk to.
>
>
True.

>> 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.
>
> This flag on insertion would again report that empty arrays are not
> array like, but I guess there's only one possible ordering of the
> elements of the empty set so it's moot.
>

You are correct, but I would like to take the opportunity to emphasize
that I propose the flag only as a single piece of evidence, but not as
the only piece of evidence for consideration in the isArrayLike
decision.


More information about the es-discuss mailing list