I have heard that ES6 now finally permits subclassing Array. Here's an example given by
class Stack extends Array {
constructor() { super() }
top() { return this[this.length - 1]; }
}
var s = new Stack();
s.push("world");
s.push("hello");
console.log(s.top()); // "hello"
console.log(s.length); // 2
Sure, that works. But in Traceur at least, setting the length explicitly does not truncate the array. And when printing via console.log, the output is in object form rather than array form, suggesting that somebody is not looking at it as a "real" array.
Is this a problem with how Traceur implements subclassing built-in objects, or a limitation of ES6?
The problem is that you are overriding the constructor. If you remove your
constructor () { super(); }
, your example works perfectly, including s.length = 0 truncating the array.Long answer
In the normal case, the subclassing in Ecmascript 6 is just syntactic sugaring, so it still does the prototypical chaining that Ecmascript 5 does. This means that extending types in Traceur is in most cases exactly the same as extending in "real" ecmascript 6.
Array instances are special – the ECMAScript 6 specification calls them exotic. Their handling of the property length can’t be replicated via normal JavaScript. If you invoke your constructor then an instance of Stack is created, not an exotic object (exotic is actually the official name in the ES6 spec).
But do not despair, the solution is not provided by the
class extends
sugaring itself, but by the (re)introduction of the__proto__
property.The solution
Ecmascript 6 reintroduces the writable
__proto__
property. It was once only available on Firefox and was deprecated, but is now back in full force in ES6. This means that you can create a real array and then "upgrade" it to your custom class.So now you can do the following:
Short answer
So subclassing should work in ES6. You might have to use the
__proto__
trick manually if they have not manage to sugar the process using the newclass extends
syntax with some yet undisclosed trickery. You will not be able to use the transpilers such as Traceur and Typescript to accomplish this in ES5, but you might be able to use the code above in ES5 using Firefox that (as far as I remember) have supported__proto__
for quite some time.