Невозможно продлить backbone.events в coffeescript
Я получаю сообщение об ошибке:
Uncaught TypeError: Cannot read property 'constructor' of undefined
При объявлении следующего класса:
class ViewHelpers extends Backbone.Events
Я могу использовать один и тот же синтаксис для расширения Backbone.Router, Views, Model и т.д. Вот компилируемый javascript, который я написал в кратком журнале, чтобы убедиться, что Backbone.Events был там
__t('views').ViewHelpers = (function(_super) {
#how i know it is definied here
console.log(_super.trigger)
__extends(ViewHelpers, _super);
function ViewHelpers() {
return ViewHelpers.__super__.constructor.apply(this, arguments);
}
return ViewHelpers;
})(Backbone.Events);
Таким образом, строка, вызывающая ошибку,
ViewHelpers.__super__.constructor.apply(this, arguments);
Чем отличается метод __extends(), который будет работать для Backbone.View, а не Backbone.Events?
Ответы
Ответ 1
Это потому, что Backbone.Events
не является "классом", поэтому он не может быть расширен, это "модуль", который можно смешивать с другими объектами (см. docs здесь). В терминах JavaScript это означает, что это не Function
, который может быть вызван как конструктор (т.е. new Backbone.Events
выдаст ошибку), это просто простой объект JS, свойства (методы которого) могут быть назначены другим объектам, чтобы сделать их диспетчеров событий.
В CoffeeScript вы можете перемешать Backbone.Events
в свои объекты при их создании:
class ViewHelpers
constructor: ->
_.extend @, Backbone.Events
Или вы можете просто расширить прототип класса и избежать использования этих методов в качестве (собственных) свойств всех экземпляров ViewHelpers
:
class ViewHelpers
_.extend @prototype, Backbone.Events
Эти два подхода должны работать и позволить вам создавать экземпляры и использовать ViewHelpers в качестве диспетчеров событий:
vh = new ViewHelpers
vh.on 'foo', -> alert 'bar'
vh.trigger 'foo'
Ответ 2
Там другой способ (из того, что ответил @epidemian), который не предполагает копирование Backbone.Events
в новый объект для использования в качестве вашего прототипа - вместо этого используйте Object.create
для создания нового объекта для использования в качестве своего прототипа, используя Backbone.Events
в качестве своего прототипа.
class ViewHelpers
@prototype = Object.create(Backbone.Events)
Теперь прототип ViewHelpers
'- это новый пустой объект, прототипом которого является Backbone.Events
. Вы можете определять методы на прототипе ViewHelpers
', не затрагивая Backbone.Events
, но все методы Backbone.Events
по-прежнему доступны для ViewHelpers
, без необходимости копировать их в новый объект. Это не только экономит (минимальное количество) памяти, но если вы закончите добавление к Backbone.Events
позже, все ViewHelpers
увидят это изменение.
Для этого вам понадобится браузер с функцией ES5 Object.create
или a Object.create
polyfill.
Ответ 3
Чтобы опираться на отличный ответ от @epidemian, я бы добавил это, это немного взломал, но он позволяет вам писать свой класс с помощью оператора extends
, как вы указали в вопросе (который позволяет вам называть super
для всех методов Backbone.Events
):
class Events
_.extend Events.prototype, Backbone.Events
class CustomEvents extends Events
trigger: (event, etc...) ->
# You can add overrides before
super "custom:#{event}", etc...
# or after the super class methods
Было бы здорово работать с вызовом _.extend
в функции Events.constructor
, но я не мог заставить его работать...