Mocha + Babel заменяет класс, расширяющий массив на массив [duplicate]

1

Я организовал проект с Моккой и Вавилоном.

Если я создам класс, который расширяет Array и вызывает метод этого класса в экземпляре, он работает в консоли, но не проходит тест с Mocha + Babel:

Кажется, что экземпляр воспринимается как экземпляр массива вместо расширенного класса.

Класс:

class A extends Array {

    hello() {
        return "hi"
    }
}

Тест:

import { expect, assert } from 'chai'
import { A } from 'a'

describe('A', () => {

    it('Should have a property', () => {        
        const result = new A();
        expect(result).to.have.property('hello')
    })

    it('Should be of the good type', () => {        
        const result = new A();
        expect(result).to.be.an.instanceOf(A)
    })


}
)

И две ошибки, которые я получаю:

  • AssertionError: ожидается, что [] имеет свойство 'hello'
  • AssertionError: ожидается [], чтобы быть экземпляром A

Любой способ исправить это?

Теги:
ecmascript-6
mocha
babeljs

1 ответ

1
Лучший ответ

Я предполагаю, что вы используете Babel, чтобы перевести это на ES5.

Array не ведет себя так же, как другие конструкторы. Для ES5 на самом деле нет эквивалентного синтаксиса, поскольку в ES5 это было даже невозможно. Таким образом, то, что Babel генерирует в попытке создать эквивалентный синтаксис, не будет работать так, как вы ожидали.

Если вы посмотрите на сгенерированный код, вы найдете эту строку:

return _possibleConstructorReturn(this, (A.__proto__ || Object.getPrototypeOf(A)).apply(this, arguments));

На этом этапе A.__proto__ будет Array, и конструктору не было дано никаких аргументов, поэтому он вызывает Array.apply(this, []) и передает результат аргументу call _possibleConstructorReturn.

В _possibleConstructorReturn вы найдете эту строку:

return call && (typeof call === "object" || typeof call === "function") ? call : self; }

В большинстве случаев вызов, apply к конструктору (вызов его без new), будет возвращен undefined. Таким образом, эта функция возвращает self в параметр, который является this из застройщик вызова. A

Array не ведет себя как обычный конструктор. Если вы вызовете его без new, он все равно вернет массив. Итак, что вы получаете от своего конструктора A - это просто старый массив.

Могут быть способы обойти это, но Вавилон не поддерживает. Если честно, если вам нужен ваш код для работы в ES5, вы, вероятно, не должны пытаться распространять такие массивы. :\

То, что часто работает в качестве альтернативы, - это написать простой класс, в котором хранится массив как свойство, с методами обертки для операций массива, в которых вы нуждаетесь. Скажем, метод get используется вместо доступа к свойствам квадратных скобок, push которое просто вызывает push на завернутый массив.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню