Skip to content

Instantly share code, notes, and snippets.

@xavierm02
Created October 25, 2011 15:25
Show Gist options
  • Save xavierm02/1313126 to your computer and use it in GitHub Desktop.
Save xavierm02/1313126 to your computer and use it in GitHub Desktop.
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.
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;
}( ) );
@padolsey
Copy link

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.

@xavierm02
Copy link
Author

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

@xavierm02
Copy link
Author

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...

@padolsey
Copy link

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?

@xavierm02
Copy link
Author

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

@padolsey
Copy link

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?

@xavierm02
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment