Subclassing an array and array methods

Allen Wirfs-Brock allen at wirfs-brock.com
Sat Nov 12 10:05:28 PST 2011


On Nov 12, 2011, at 9:38 AM, Axel Rauschmayer wrote:

> I misunderstood the problem: I thought there was something peculiar about an array instance (the first object in the prototype chain), but it’s about the Array constructor not being invocable as a function (right?).

I'm not sure what you mean about "not invocable as a function".  
   ArraY(1,2,3,4)
works just fine an creates an array instance.

> 
> Wouldn’t it be easier to introduce a generic method Array.prototype.init() that behaves like quirk-free Array.prototype.constructor()?
> 
> Use case 1: Create an array subtype:
>    let SubArray = Array <| function(...args) {
>        super.init(...args); // instead of super.constructor(...args)
>    }

the problem is that the "specialness" of arrays is mostly that they have their own alternative definition of [[DefineOwnProperty]].  By the time you reach the init call, the new object has already been created with the default [[DefineOwnProperty]]  behavior.  It isn't clear, that it is possible or reasonable to change such internal behaviors after an object is created. myProto<| [ ] avoid the problem by forcing creation (via [ ] ) of an object with the special array [[DefineOwnProperty]].

There are potentially other ways around this problem.  For example, there could be a well know private name property that could be attached to a constructor that would force |new| to create instances that use the Array internal methods.


> Use case 2: Avoid the length pitfall:
>    var arr = new Array().init(5); // same as [5]
> 
> - Another, possibly stupid, idea: Could Array.prototype.constructor not point to Array, but to a function like Array.prototype.init() – that doesn’t create a new instance and doesn’t have the length quirk?

Not compatible with existing code. 


> 
> - One more: Introduce a constant CLEAN
>    let SubArray = Array <| function(...args) {
>        super.constructor(CLEAN, ...args);
>    }
>    var arr = new Array(CLEAN, 3); // the same as [3]
> 
> - Creating a subtype CleanArray or ExtensibleArray also seems feasible. Engines could optimize internally so that it’s basically the constructor being swapped for a quirk-free implementation.

I don't think that the length quirk is the major issue anyone is concerned about.

> 
> Whatever the solution, it’s obviously applicable to Date, Error, etc., as well.


Those are actually easer to make subclassable because they don't redefine any of the internal methods.  All that is needed is to convert their private state into private named properties.  That's already on my todo list.

Allen


More information about the es-discuss mailing list