Подтвердить что ты не робот

Расширение массива с классами ES6

Я слышал, что 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?

4b9b3361

Ответ 1

Длинный ответ

В нормальном случае подкласс в Экскрипте 6 является просто синтаксическим сахарированием, поэтому он все еще выполняет прототипную цепочку, которую делает Экскрипт 5. Это означает, что распространенные типы в Traceur в большинстве случаев точно такие же, как в "реальном" ecmascript 6.

Экземпляры массива являются специальными - спецификация ECMAScript 6 называет их экзотическими. Их обработка длины свойства не может быть реплицирована через обычный JavaScript. Если вы вызываете свой конструктор, то создается экземпляр Stack, а не экзотический объект (экзотика на самом деле является официальным именем в спецификации ES6).

Но не отчаивайтесь, решение не обеспечивается сахарированием class extends, а с помощью (re) введения свойства __proto__.

Решение

Экзаменск 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__ вручную, если им не удастся сгладить процесс, используя новый синтаксис class extends с некоторыми еще нераскрытыми обманами. Вы не сможете использовать транспиляторы, такие как Traceur и Typescript, чтобы выполнить это в ES5, но вы можете использовать приведенный выше код в ES5 с помощью Firefox, который (насколько я помню) поддерживал __proto__ для довольно долгое время.

Ответ 2

Проблема заключается в том, что вы переопределяете конструктор. Если вы удалите свой constructor () { super(); }, ваш пример отлично работает, включая s.length = 0, усекающий массив.