我听说ES6现在终于允许子类化Array。这是一个例子

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


当然可以。但是至少在Traceur中,显式设置长度不会截断数组。当通过console.log打印时,输出是对象形式而不是数组形式,这表明有人没有将其视为“真实”数组。

Traceur如何实现内置对象的子类化或ES6的限制是否存在问题?

最佳答案

长答案

在正常情况下,Ecmascript 6中的子类只是语法加糖,因此它仍然像Ecmascript 5那样进行原型链。这意味着在大多数情况下,Traceur中的扩展类型与“真实” ecmascript 6中的扩展类型完全相同。

数组实例很特殊– ECMAScript 6规范称它们为奇异的。他们对属性长度的处理无法通过常规JavaScript复制。如果调用构造函数,则会创建Stack实例,而不是奇异对象(exotic实际上是ES6规范中的正式名称)。

但是请不要失望,解决方案不是由class extends加糖本身提供的,而是由(cc)属性的(重新)引入提供的。

解决方案

Ecmascript 6重新引入了可写的__proto__属性。它曾经仅在Firefox上可用并且已过时,但现在在ES6中重新全面使用。这意味着您可以创建一个真实的数组,然后将其“升级”到您的自定义类。

因此,您现在可以执行以下操作:

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


简短答案

因此,子类化应在ES6中工作。如果他们无法使用新的__proto__语法和一些尚未公开的技巧来加糖该过程,则可能必须手动使用__proto__技巧。您将无法在ES5中使用Traceur和Typescript之类的转译器来完成此任务,但是您可能能够在ES5中使用上面的代码(使用Firefox)(据我所记得)已经在很大程度上支持class extends时间。

10-06 08:21
查看更多