"not a Date object" vs. "not an object with [[Class]] of ''Date''"

# Brendan Eich (15 years ago)

KangaX brought this up in

perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array

and proxies are of no avail. To make an array-like using ES5 is possible but [[Class]] won't lie, and that is still true with Proxy.create instead of Object.create.

As we have discussed, [[Class]] is very much a nominal type tag, so it is not something we want to be forged by an impostor. But perhaps as Allen mentioned in the TC39 meeting this week, [[ClassName]] could be separated from [[Class]], and forged without problem. Proxies would want to be able to present a specific [[ClassName]], but a non-varying one -- so probably a trailing Proxy.create parameter. Thoughts?

# Oliver Hunt (15 years ago)

I really don't like the idea of using proxies simply to essentially create an array with a custom prototype.

My understanding of what is wanted (in terms of subtyping an array) is an ability to have something like

var arr = new MyArray()

Where 'new MyArray' behaves in essentially the same manner as 'new Array', however it produces an object along the lines of

<an array instance> <- <a custom prototype> <- <array prototype>

In a engine that support mutating proxies this would be equivalent to:

function MyArray() { var result = Array.apply(null, arguments); result.proto = MyArray.prototype; return result; }

MyArray.prototype = Object.create(Array.prototype);

If my understanding of this desired behaviour is correct, i think a better solution would be to make an API that could generate the MyArray function.

# Brendan Eich (15 years ago)

On Oct 1, 2010, at 6:24 PM, Oliver Hunt wrote:

I really don't like the idea of using proxies simply to essentially create an array with a custom prototype.

Implement proxies, then we'll talk :-P.

My understanding of what is wanted (in terms of subtyping an array) is an ability to have something like

var arr = new MyArray()

Where 'new MyArray' behaves in essentially the same manner as 'new Array', however it produces an object along the lines of

<an array instance> <- <a custom prototype> <- <array prototype>

I don't think the use-case is satisfied by a direct Array instance, whatever its proto. That's the rub.

# Oliver Hunt (15 years ago)

On Oct 1, 2010, at 6:55 PM, Brendan Eich wrote:

On Oct 1, 2010, at 6:24 PM, Oliver Hunt wrote:

I really don't like the idea of using proxies simply to essentially create an array with a custom prototype.

Implement proxies, then we'll talk :-P.

My understanding of what is wanted (in terms of subtyping an array) is an ability to have something like

var arr = new MyArray()

Where 'new MyArray' behaves in essentially the same manner as 'new Array', however it produces an object along the lines of

<an array instance> <- <a custom prototype> <- <array prototype>

I don't think the use-case is satisfied by a direct Array instance, whatever its proto. That's the rub.

What part of the use case is not covered? From reading the blog post (which suggests something similar to this) kangax says the problem with this solution is the use of the non-standard proto, not that it doesn't achieve the desired result

# Brendan Eich (15 years ago)

On Oct 1, 2010, at 7:00 PM, Oliver Hunt wrote:

What part of the use case is not covered? From reading the blog post (which suggests something similar to this) kangax says the problem with this solution is the use of the non-standard proto, not that it doesn't achieve the desired result

The crucial issue is whether a non-Arrray instance is essential:

MyArray instance --[proto]--> MyArray.prootype --[proto]--> Array.prototype --[proto]--> Object.prototype

Cc'ing kangax.

# Juriy Zaytsev (15 years ago)

On Fri, Oct 1, 2010 at 10:00 PM, Oliver Hunt <oliver at apple.com> wrote:

On Oct 1, 2010, at 6:55 PM, Brendan Eich wrote:

On Oct 1, 2010, at 6:24 PM, Oliver Hunt wrote:

I really don't like the idea of using proxies simply to essentially create an array with a custom prototype.

Implement proxies, then we'll talk :-P.

My understanding of what is wanted (in terms of subtyping an array) is an ability to have something like

var arr = new MyArray()

Where 'new MyArray' behaves in essentially the same manner as 'new Array', however it produces an object along the lines of

<an array instance> <- <a custom prototype> <- <array prototype>

I don't think the use-case is satisfied by a direct Array instance, whatever its proto. That's the rub.

What part of the use case is not covered? From reading the blog post (which suggests something similar to this) kangax says the problem with this solution is the use of the non-standard proto, not that it doesn't achieve the desired result

Object.create([]) doesn't solve the problem of subclassing an array, since created object is still a plain Object object and so has [[Get]] and [[Put]] that act like Object's ones, not Array ones.

var o = Object.create([]); o[2] = 'x'; o.length; /* 0, not 3 as it should be */

o.length = 0; o[2]; /* "x", not undefined as it should be */

In ES3 (w/o extensions) you can't do much about it, but in ES5 it's possible to fiddle with length getter/setter to make object act like an array (the performance of such implementation turns out to be incredibly slow, for obvious reasons).

So now when you solved "magic" length property (considering that we're in ES5), and have a plain Object object with [[Prototype]] referencing Array.prototype, you still have immutable [[Class]]. So Array.isArray would return false for this pseudo-array object (it could be somehow overwritten to account for it, but this is kind of getting too far); and then there are places in spec, where wrong [[Class]] ("Object", not "Array") will make for a completely different outcome. For example, JSON.stringify:

var o = Object.create([]); o[2] = 'x';

JSON.stringify(o); // "{"2":"x","length":0}" not [null,null,"x"]

Settable [[Prototype]] helps because you can just create an array object, then inject something into its prototype chain (right before Array.prototype). And that extra object can have any methods you wish on subarray instances — all without polluting global Array.prototype.

[...]

# Tom Van Cutsem (15 years ago)

We have previously discussed the Proxy.create(handler, proto, className) design and I think it's feasible. One issue is what should happen to the proxy's [[ClassName]] when it becomes fixed. In the current design, a fixed object proxy can be made indistinguishable from a regular object. That's no longer the case if the fixed proxy should retain its custom [[ClassName]] (which I think is desirable).

That said, if proxies would be able to virtualize something like [[ClassName]], I think the array subclassing use case can be supported as follows (I'm sure there's a much better way to do this, but this is just a proof-of-concept):

function createArray(proto, initArray) { // proto is assumed to delegate to Array.prototype // initArray is assumed to be a real Array var handler = { get: function(r,n) { if (!initArray.hasOwnProperty(n)) { return proto[n]; } else { return initArray[n]; } }, set: function(r,n,v) { return initArray[n] = v; }, // other traps }; return Proxy.create(handler, proto, "Array"); };

var SubArray = Object.create(Array.prototype); SubArray.last = function() { return this[this.length - 1]; };

var myArray = createArray(SubArray, [1,2,3]); myArray.length; // 3 myArray.last(); // 3 myArray[10] = 42; myArray.length; // 11 myArray.last(); // 42 Object.prototype.toString.call(myArray); // [object Array] myArray instanceof Array; // true myArray.toString(); // 1,2,3,,,,,,,,42

I tested this in a recent tracemonkey shell with support for Proxies and it seems to work (except that currently, of course, proxies cannot virtualize [[ClassName]] so the proxy-array still prints as [object Object])

2010/10/1 Juriy Zaytsev <kangax.dev at gmail.com>

# Dmitry A. Soshnikov (15 years ago)

In the same success it may be a simple very-generic meta-constructor (that is, Object.create) which may accept a className. That what have been discussed many times (including the only approach for today with injecting with proto), including in the recent talk mail.mozilla.org/pipermail/es5-discuss/2010-September/003708.html.

E.g.:

Object.create({ prototype:<...>, class: "Array", descriptor: { ... } });

or (the current, but extended way -- which won't bring backward compats issues)

Object.create(prototype, descriptor, "Array");

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him).

Dmitry.

# Brendan Eich (15 years ago)

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him).

Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited.

# Jorge (15 years ago)

On 02/10/2010, at 15:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him).

Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited.

Why not simply spec an Array.create() ?

-no need to redefine what an array is. -no need to learn new concepts ( we're used to Object.create() already ) -easy to grasp, expected behaviour. -it's a 3-liner that would take no more than 3 minutes to implement in JS in any current UA. -it would just need to be in the ES specs.

# Dmitry A. Soshnikov (15 years ago)

On 02.10.2010 17:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him). Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited.

Yep, true, but if we have ability to specify the [[Class]] -- we'll have overloaded [[DefineOwnProperty] (or [[Put]] in ES3).

Here's this ad-hoc (with using proto injection) implementation: gist.github.com/607668

By the way, at first glance, the ability to specify [[Class]] with using first level of inheritance is not so convenient and needed. Because with the same success we may create a simple array and augment it with needed properties. However, starting from the second and later inheritance levels -- it may be convenient.

This is if to talk about prototypal inheritance. If to consider class-based inheritance (that is, with using constructors), possibly it can be sense in the special meta-constructor (a constructor of constructors) which may specify, objects of what kind (of what [[Class]]) a newly created constructor may produce.

P.S.: in addition, the Proxy constructor may also accept className parameter. But repeat -- proxies are needed to trap the property access. If a user just want to have Array.prototype in inheritance chain and at the same time have an object of the "Array" kind, he just creates it with specifying this kind. He don't need to write a proxy's handler for that. Howerver, if he does need the catcher -- he creates a proxy of "Array" kind.

Dmitry.

# Dmitry Soshnikov (15 years ago)

Ok, here's also implemented meta-constructor. Constructors created by this meta-constructor may produce also objects with specified [[Class]]. Additionally I made a sugar with inheriting from passed "className.prototype" object.

It may be found here: gist.github.com/607668

Again, non-standard proto is used to inject the needed prototype (however, at implementation level it doesn't matter).

Dmitry.

# Alex Russell (15 years ago)

On Oct 2, 2010, at 6:49 AM, Jorge wrote:

On 02/10/2010, at 15:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him).

Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited.

Why not simply spec an Array.create() ?

Or why not simply expose the [[Get]] and [[Set]] protocol for Array so that it can be implemented directly by sub-classers? Having it hidden away in some primitive property of Array is what makes prototypal extension for Arrays insufficient in the first place, right?

# Alex Russell (15 years ago)

On Oct 2, 2010, at 10:45 AM, Alex Russell wrote:

On Oct 2, 2010, at 6:49 AM, Jorge wrote:

On 02/10/2010, at 15:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him).

Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited.

Why not simply spec an Array.create() ?

Or why not simply expose the [[Get]] and [[Set]] protocol for Array

Sorry, I meant [[Put]].

# Brendan Eich (15 years ago)

On Oct 2, 2010, at 6:49 AM, Jorge wrote:

On 02/10/2010, at 15:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him).

Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited.

Why not simply spec an Array.create() ?

-no need to redefine what an array is.

It's not clear from kangax's blog post that an array with an extra object on its prototype chain before Array.prototype is enough, but if it is, then yes: Array.create is simpler and more direct than using proxies.

-no need to learn new concepts ( we're used to Object.create() already )

There's definitely a new concept here. Right now you can't create an array instance whose [[Prototype]] is not some Array.prototype. Array.create changes that.

-easy to grasp, expected behaviour. -it's a 3-liner that would take no more than 3 minutes to implement in JS in any current UA. -it would just need to be in the ES specs.

"3-liner", "3 minutes" and "just" need demonstration. Are you writing the code and spec patches? Talk is cheap :-|. Arrays are highly optimized in modern engines (up to some array sparseness limit). Adding a prototype object shouldn't hurt if the new proto-object contains no indexed properties, though.

# Dmitry A. Soshnikov (15 years ago)

On 03.10.2010 0:51, Brendan Eich wrote:

On Oct 2, 2010, at 6:49 AM, Jorge wrote:

On 02/10/2010, at 15:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him). Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited. Why not simply spec an Array.create() ?

-no need to redefine what an array is. It's not clear from kangax's blog post that an array with an extra object on its prototype chain before Array.prototype is enough, but if it is, then yes: Array.create is simpler and more direct than using proxies.

-no need to learn new concepts ( we're used to Object.create() already ) There's definitely a new concept here. Right now you can't create an array instance whose [[Prototype]] is not some Array.prototype. Array.create changes that.

-easy to grasp, expected behaviour. -it's a 3-liner that would take no more than 3 minutes to implement in JS in any current UA. -it would just need to be in the ES specs. "3-liner", "3 minutes" and "just" need demonstration. Are you writing the code and spec patches? Talk is cheap :-|. Arrays are highly optimized in modern engines (up to some array sparseness limit). Adding a prototype object shouldn't hurt if the new proto-object contains no indexed properties, though.

Off-topic: what's wrong with the es-archive? Take a look please: esdiscuss/2010-October/thread I sent reply with implemented extended Object.create and meta-constructor (meta-class) but it's not displayed there. Maybe it's not reached es-discuss at all? If it didn't (by some reason), consider this implementation (gist.github.com/607668). It allows to create objects of any [[Class]] with needed inheritance chains.

Dmitry.

# Dmitry A. Soshnikov (15 years ago)

On 03.10.2010 0:58, Dmitry A. Soshnikov wrote:

On 03.10.2010 0:51, Brendan Eich wrote:

On Oct 2, 2010, at 6:49 AM, Jorge wrote:

On 02/10/2010, at 15:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him). Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited. Why not simply spec an Array.create() ?

-no need to redefine what an array is. It's not clear from kangax's blog post that an array with an extra object on its prototype chain before Array.prototype is enough, but if it is, then yes: Array.create is simpler and more direct than using proxies.

-no need to learn new concepts ( we're used to Object.create() already ) There's definitely a new concept here. Right now you can't create an array instance whose [[Prototype]] is not some Array.prototype. Array.create changes that.

-easy to grasp, expected behaviour. -it's a 3-liner that would take no more than 3 minutes to implement in JS in any current UA. -it would just need to be in the ES specs. "3-liner", "3 minutes" and "just" need demonstration. Are you writing the code and spec patches? Talk is cheap :-|. Arrays are highly optimized in modern engines (up to some array sparseness limit). Adding a prototype object shouldn't hurt if the new proto-object contains no indexed properties, though.

Off-topic: what's wrong with the es-archive? Take a look please: esdiscuss/2010-October/thread I sent reply with implemented extended Object.create and meta-constructor (meta-class) but it's not displayed there. Maybe it's not reached es-discuss at all? If it didn't (by some reason), consider this implementation (gist.github.com/607668). It allows to create objects of any [[Class]] with needed inheritance chains.

Another variant btw, is just to set special internal property for the constructor. This property specifies the [[Class]] of objects created by the constructor.

function Foo() { this.push.apply(this, [1, 2, 3]); }

Object.setObjectsClass(Foo, "Array");

var foo = new Foo(); foo.length // 3 Array.isArray(foo); // true // etc.

# Brendan Eich (15 years ago)

On Sep 6, 2010, at 7:17 AM, Dmitry A. Soshnikov wrote:

On 02.10.2010 17:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him). Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited.

Yep, true, but if we have ability to specify the [[Class]] -- we'll have overloaded [[DefineOwnProperty] (or [[Put]] in ES3).

Here's this ad-hoc (with using proto injection) implementation: gist.github.com/607668

By the way, at first glance, the ability to specify [[Class]] with using first level of inheritance is not so convenient and needed.

Indeed. Also, I would not say this shows the abilitiy to specify [[Class]] as if that internal property could be specified as "Array" for a non-Array instance -- all you are doing is making an Array instance whose [[Prototype]] links to a user-specified object. That's novel in ES5, i.e., without settable proto and without Array.create as Jorge pointed out.

# Dmitry A. Soshnikov (15 years ago)

On 03.10.2010 1:06, Brendan Eich wrote:

On Sep 6, 2010, at 7:17 AM, Dmitry A. Soshnikov wrote:

On 02.10.2010 17:29, Brendan Eich wrote:

On Sep 6, 2010, at 1:43 AM, Dmitry A. Soshnikov wrote:

For what to create a proxy? It's only for catch-traps (yes, it may be used additionally to create a catcher with "Array" [[Class]], but without additions -- i.e. if a user wants just to inherit from Array.prototype and to have all arrays' stuff -- proxies are not needed to him). Proxies are required to update length to be one greater than index (property name-string P such that ToString(ToUint32(P)) == P and ToUint32(P) is not 2^32 - 1) when setting an indexed property. Array's magic [[Put]] is not inherited.

Yep, true, but if we have ability to specify the [[Class]] -- we'll have overloaded [[DefineOwnProperty] (or [[Put]] in ES3).

Here's this ad-hoc (with using proto injection) implementation: gist.github.com/607668

By the way, at first glance, the ability to specify [[Class]] with using first level of inheritance is not so convenient and needed. Indeed. Also, I would not say this shows the abilitiy to specify [[Class]] as if that internal property could be specified as "Array" for a non-Array instance -- all you are doing is making an Array instance whose [[Prototype]] links to a user-specified object.

Yeah, of course, but it's just a shim with resources I have (JS) :) At lower level of implementation, I'd operate with different approach.

That's novel in ES5, i.e., without settable proto and without Array.create as Jorge pointed out.

Yes, but Array.create should do the same. Implementation is abstract and isn't essential. The end result is essential. With the same end result all implementation fit (if to consider only the semantics of course).

# Andrea Giammarchi (15 years ago)

this.push.apply(this, [1, 2, 3]);

... mmmm, Dmitry, WTF :D

this.push(1, 2, 3);

easy :P

I still don't like the idea of "injectable [[Class]]" for user defined objects ... JS follows massive cross libraries approach ... please don't create a chaos even worst than the one we already have with randomly extended native prototypes.

, Andrea Giammarchi

# Dmitry A. Soshnikov (15 years ago)

On 03.10.2010 1:56, Andrea Giammarchi wrote:

this.push.apply(this, [1, 2, 3]);

... mmmm, Dmitry, WTF :D

this.push(1, 2, 3);

easy :P

Ah, it was copy-pasted from more generic case when data came from arguments.

I still don't like the idea of "injectable [[Class]]" for user defined objects ... JS follows massive cross libraries approach

I just wanted to make it more generic (since Brendan and Tom were saying about "className" parameter for "Proxy.create"; so I made it for for "Object.create"). In less generic case, "Array.create" can be enough.

But because in JS prototype-based and class-based techniques are combined (including some Java's class-based syntactic constructs which lead to semantic meaning), the logical semantics in general may look also "broken". E.g.

foo instanceof Array // false

but at the same time:

Array.isArray(foo) // true

And these are quite normal situations (see the last lines in my code) with combining semantics of class- and proto-based approaches. Actually, this is what about the title of this thread.

P.S.: and regarding Array.create, it can be easily implemented in terms of abstaction with "Object.create" with accepting the "className", or more desugared and ad-hoc:

Object.defineProperty(Array, "create" { value: function (proto, desc) { var res = []; res.proto = proto; return Object.defineProperties(res, desc); } });

Of course, at implementation level it will look like (in generic case):

  1. Let O be a new native ECMAScript object .
  2. Set the [[Class]] internal property of F to /className/. 3 ...

Or in exact case can be so:

  1. Let obj be the result of creating a new object as if by the expression new Array() where Array is the standard built-in constructor with that name.
  2. Set the [[Prototype]] internal property of obj to O.
  3. ...

Dmitry.

# Dmitry A. Soshnikov (15 years ago)

And one more thing to note, is that "Array.create" in general (if not to say -- /only/) is for the case of having objects which [[Class]] is "Array". It's very inconvenient (because of default property values of the descriptor) to define an array's elements with this function (I've updated the source with "Array.create" and the example):

var baz = Array.create(bar, { // array elements (very inconvenient) 0: {value: 1, writable: true, enumerable: true, configurable: true}, 1: {value: 2, writable: true, enumerable: true, configurable: true}, 2: {value: 3, writable: true, enumerable: true, configurable: true}, // methods info: { value: function getInfo() { return [this.length, this.size, this.count].join(","); } } });

Dmitry.

# Andrea Giammarchi (15 years ago)

I don't know man, I kinda like the possibility, but I am pretty sure we gonna end up trying to figure out via weird tricks if an Array is a native one or not (e.g. Array.isReallyAnArray(obj)) ... however, it's good to have more power than less ;-)

, Andrea Giammarchi

# Jorge (15 years ago)

On 02/10/2010, at 22:51, Brendan Eich wrote:

On Oct 2, 2010, at 6:49 AM, Jorge wrote:

Why not simply spec an Array.create() ?

-no need to redefine what an array is.

It's not clear from kangax's blog post that an array with an extra object on its prototype chain before Array.prototype is enough, but if it is, then yes: Array.create is simpler and more direct than using proxies.

Kangax's example [*1] using proto for subclassing is cutting the "extra object" proto chain arbitrarily, for no good reason : he's assuming that the object being passed as the prototype for the subclass (the "extra object") is not an instanceof Array.

But it must be an instanceof Array because it must have Array.protoype in its prototype chain, so he's inserting it, cutting the proto chain, mutating liberally the provided "extra object".

But it's not exactly nice to mutate the "extra object" in any way. Imagine for a second that Object.create() did the same... :-/

I think that Array.create(protoArray) should do no more than :

1.- check that protoArray is an instanceof Array, 2.- insert it into the [[prototype]] of a new [ ]. 3.- return the new [ ].

-no need to learn new concepts ( we're used to Object.create() already )

There's definitely a new concept here. Right now you can't create an array instance whose [[Prototype]] is not some Array.prototype. Array.create changes that.

I meant : in Object.create(protoObject) you provide a protoObject object and obtain a new object whose [[prototype]] is protoObject, In Array.create(protoArray) you provide a protoArray array and obtain a new array whose [[prototype]] is protoArray.

-easy to grasp, expected behaviour. -it's a 3-liner that would take no more than 3 minutes to implement in JS in any current UA. -it would just need to be in the ES specs.

"3-liner", "3 minutes" and "just" need demonstration. Are you writing the code and spec patches? Talk is cheap :-|.Arrays are highly optimized in modern engines (up to some array sparseness limit). Adding a prototype object shouldn't hurt if the new proto-object contains no indexed properties, though.

Oops, sorry, I apologize. As a mereuser* from my perspective it seems to be as simple as :

[ the "show me code" part :-) ]

Array.create= function ArrayCreate (protoArray) { if ( !(protoArray instanceof Array) ) throw Error("protoArray must be an instanceof Array"); var newArray= [ ]; newArray.proto= protoArray; return newArray; }