Extending Array with ES6 classes

随声附和 提交于 2019-12-18 03:54:28

问题


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?


回答1:


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:

function Stack(len) {
    var inst = new Array(len);
    inst.__proto__ = Stack.prototype;
    return inst;
}
Stack.prototype = Object.create(Array.prototype);  

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




回答2:


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.



来源:https://stackoverflow.com/questions/26700164/extending-array-with-es6-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!