public
Created

A way to "subclass" Array. It will fail if you add something at an index > the length of the array. Doesn't provide Array as [[Class]] either.

  • Download Gist
gistfile1.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
var FakeArray = ( function ( ) {
function FakeArray( ) {
var fakeArray = Object.create( FakeArray.prototype );
var realArray = Array.apply( Object.create( Array.prototype ), arguments );
Object.defineProperty( fakeArray, '', {
value: realArray
} );
forwardIndexesUntil( realArray.length );
return fakeArray;
}
var prototypeOfFakeArray = FakeArray.prototype = Object.create( Array.prototype, {
constructor: {
value: FakeArray,
configurable: true,
writable: true
},
length: {
get: function ( ) {
return this[ '' ].length;
},
set: function ( value ) {
this[ '' ].length = value;
forwardIndexesUntil( value );
},
configurable: true,
enumerable: true
}
} );
function forwardIndex( index ) {
Object.defineProperty( prototypeOfFakeArray, index, {
get: function ( ) {
return this[ '' ][ index ];
},
set: function ( value ) {
this[ '' ][ index ] = value;
forwardIndexesUntil( index + 1 );
},
configurable: true
} );
}
function forwardIndexesUntil( index ) {
for ( var i = index; i > greatestForwardedIndex; --i ) {
forwardIndex( i );
}
}
var greatestForwardedIndex = 0;
forwardIndex( 0 );
var prototypeOfArray = Array.prototype;
var propertyDescriptor;
for ( var name in prototypeOfArray ) {
if ( prototypeOfArray.hasOwnProperty( name ) ) {
propertyDescriptor = Object.getOwnPropertyDescriptor( prototypeOfArray, name );
propertyDescriptor.value = ( function ( value ) {
return function ( ) {
return value.apply( this[ '' ], arguments );
};
}( ) );
Object.defineProperty( prototypeOfFakeArray, name, propertyDescriptor );
}
}
return FakeArray;
}( ) );

With private names the getters and setters could be shared...
And with proxies, you would forward everything with one setter and one getter.

As you mentioned, this'll throw an error:

f = new FakeArray(1,2,3);
f.push(4);

I can't find a way to subclass Arrays using proxies properly. I can't set the __proto__ of the proxy itself, either. I'm not sure that it's possible.

Fixed :)
I do cheat by using the '' property but it could be replaced by a name object later and become a real private property.

And subclassing arrays with Proxies would be weird since when Proxies will arrive for real, there will also be <| and it would be much easier to subclass with it...

I guess you could use a scoped var instead of storing something on the fakeArray object. (no need to use this[''] .. just ref realArray directly, right?

Intrigued -- what's the <l you speak of?

Well if I use a scoped var, it'll fail... Because there is one realArray per instance of FakeArray. I could use parallel arrays but it'd increase the lookup...
Or I could do it with WeakMaps too, when they arrive.
EDIT : Or you would need to redefine all getters and setters for every instance and if you do, you better simply take a normal array [ ] and add the methods you want on it...

And it is <| and not <1. See http://wiki.ecmascript.org/doku.php?id=harmony%3aproto_operator

Good point about having to redefine all getters/setters. Not worth it.

I had no idea what <| was being discussed. It doesn't seem like something that'll get implemented any time soon though since it's a change of syntax. ES implementations are more likely to implement Proxy, right?

Well <| isn't flagged strawman anymore. It's officially harmony. So it'll come with the rest of harmony.
And there is kind of no discussion about how it should work, I'm quite sure they decided how it was going to work and agreed. If I remember well, they're just debating about the symbol (some don't like <|).

On the contrary, on Proxies, they know they want proxies but not how exactly. So they kind of sent them in the wild to see what would happen.
If you take a look at the end of the page, you can see that Proxies have already changed a lot, whereas <| is quite fixed.

(Do not consider everything I say as true, I'm speaking of things I read / heard in english without always paying the required attention [they speak wait too much on es-discuss -.- ] and I might have misunderstood since it's not my native language)
http://wiki.ecmascript.org/doku.php?id=harmony:proxies

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.