array like objects

Brendan Eich brendan at mozilla.com
Tue Dec 15 09:54:11 PST 2009


On Dec 15, 2009, at 8:46 AM, Jorge Chamorro wrote:

> It's the same functionality provided by Object.create(), but for []  
> instead of {}.

Ah, that helps -- thanks. This is not exactly what Tucker showed,  
though.


>> Tucker is looking for a way to compose custom [[Put]] with  
>> prototype-based delegation. My reply suggested that if [[Put]] were  
>> a property name, just like "length", and looked up along the  
>> prototype chain, so that the default [[Put]] was in  
>> Object.prototype, the custom Array [[Put]] that updates .length to  
>> be one greater than the highest index were on Array.prototype (or  
>> on [] in Tucker's example, but in general on the class prototype  
>> would suffice), etc., then we would not need anything new like  
>> Array.create.
>
> The way I see it, the subclass' prototype object ought to come - 
> necessarily- before the Array.prototype object in the subclassed  
> instance's prototype chain. If not, every other existing and future  
> [] instances would be affected too. Also, because if not there would  
> be no way to create two different [] subclasses.

Sure. I was not describing Array.create or "subclasses", just  
responding to what Tucker showed:

  function MyArray () {}
  MyArray.prototype = [];

It may be that Array.create could fit his use-case instead, but if the  
idea is to make new user-defined *constructors* such as MyArray, then  
Array.create does not necessarily help. The user-defined constructor  
would have to return a new Array.create(MyArray.prototype) instance,  
and it would be stuck with the non-configurable "own" properties  
defined on Array instances.

This might or might not be desired; anyway, it's not exactly the same  
as what you proposed in reply.


> If for some reason you wanted/needed to override/shadow any/some of  
> Array.prototype's methods, isn't it that, in order to achieve that,  
> the subclass' prototype object ought to come before the  
> Array.prototype object in the instance's prototype chain ?

I don't believe I wrote otherwise.


> That, or manually extending each and every instance with own  
> properties ?
>
> AFAICS, anything that comes -in the prototype chain- after  
> Array.prototype would extend all the [] instances at once. But most  
> likely I'm missing something...

My point was that if [[Put]], which is part of what makes an Array  
instance "array-like", were delegated, along with the other internal  
methods in ES5 (which are of course specification devices, not  
concrete implementation artifacts), then what Tucker wrote -- exactly  
what he wrote -- would "work".

The reason it doesn't work is evident from a bit more REPL citing:

js>  function MyArray () {}
js>  MyArray.prototype = [];
[]
js> var a = new MyArray
js> a.length
0
js> a[9] = "length should now be 10"
"length should now be 10"
js> a.length
0

What I proposed instead (not seriously; it's more a Self _homage_ than  
anything to add to a future JS/ES, at this point) was that setting  
a[9] would look for [[Put]] in a, not find it, look in a. 
[[Prototype]], which is [] above, not find a custom [[Put]], then look  
in [].[[Prototype]] which is Array.prototype, and finally find the ES- 
specified custom [[Put]] that advances length as needed.

When the Array [[Put]] was invoked, it would be passed a as the  
directly referenced object, the receiver of the method  call (aka | 
this|). Thus, 'length' would be set directly on a by the Array [[Put]]  
internal method.

In ES specs and real implementations, internal methods and various  
corresponding implementation hooks are called based on [[Class]] of  
the directly referenced object, in contrast. No lookup for internal- 
method names that cannot be uttered in the source language is done.  
But this ancient design decision means we have "host objects" that can  
and do have inconsistent or even incorrect internal method suites.

/be


More information about the es-discuss mailing list