array like objects

Juriy Zaytsev kangax.dev at gmail.com
Tue Dec 8 11:22:39 PST 2009


On Dec 8, 2009, at 1:10 PM, Mike Samuel wrote:

> 2009/12/8 Erik Corry <erik.corry at gmail.com>:
>> 2009/12/8 Mike Samuel <mikesamuel at gmail.com>:
>>> It occurred to me after looking at the proxy strawman that it might
>>> help to nail down what "array-like" means in future drafts.  It isn't
>>> directly related to the proxy stuff though so I thought I'd start a
>>> separate thread.
>>> 
>>> I've seen quite a bit of library code that does something like
>>>   if (isArrayLike(input)) {
>>>     // iterate over properties [0,length) in increasing order
>>>   } else {
>>>     // Iterate over key value pairs
>>>   }
>> 
>> This looks fairly broken to me.  If the object has enumerable
>> properties that aren't positive integers then they don't get iterated
>> over just because some heuristic says it's array-like.  If the
>> heuristic says it's array-like then we iterate over portentially
>> billions of indexes even if it is very sparse.
> 
> All true.  And yet it is not uncommon.  See the bottom of this email
> for a quick survey of a number of libraries' uses of the array-like
> concept.
> 

[...]

> 
> Prototype.js dodges this problem by adding an each method to
> Array.prototype and others.  This obviously fails for cross-context
> Arrays, and also suffers from the large sparse array and missing
> non-array-index properties problems.
> 
> It does switch on arrays in places, and does so inconsistently though
> -- in one case (unnecessarily?) filtering out arguments objects?

If you look just a bit below those lines, you will see that this whole `concat` method is only assigned to `Array.prototype.concat` when `CONCAT_ARGUMENTS_BUGGY` is truthy.

`CONCAT_ARGUMENTS_BUGGY` feature test looks like this:

  (function() {
    return [].concat(arguments)[0][0] !== 1;
  })(1,2);

and is essentially a workaround to an "issue" with Opera, which, contrary to specs, makes `arguments instanceof Array`, yet fails to implement proper `concat` algorithm for arguments (as feature test demonstrates).

As far as `isArray` in Prototype.js, we just test for [[Class]] === "Array" (which is good across frames, but still fails across windows in IE). 

There's, of course, no silver bullet `isArray` solution for a library. It's all about specific requirements, and as long as users do not fully understand language specifics, there will be broken expectations; some will expect "arrays" to inherit from `Array.prototype` (and so have any of `Array.prototype` methods available); some will expect arrays to have special [[Put]] and `length`behavior; and others will expect array-like host objects (that neither inherit from Array, nor have special [[Put]] or [[Class]] === "Array") to be considered arrays as well.

It's all about context ;)

[...]

-- 
kangax


More information about the es-discuss mailing list