2012-06-17 16 views
15

estoy recibiendo el error:no puede extenderse backbone.events en CoffeeScript

Uncaught TypeError: Cannot read property 'constructor' of undefined 

Al declarar la clase siguiente:

class ViewHelpers extends Backbone.Events 

puedo usar la misma sintaxis para extender Backbone.Router , Vistas, modelo, etc. Aquí está el código JavaScript compilado el que he escrito en un registro rápido para asegurarse de que estaba allí 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); 

Así, la línea que causa el error es

ViewHelpers.__super__.constructor.apply(this, arguments); 

¿Qué es diferente acerca de __extends() método que trabajaría para Backbone.View y no Backbone.Events?

+0

he comentado en la diferencia entre Backbone.Events y otros objetos Backbone en una respuesta a continuación, pero me gustaría k: ¿cuál es el propósito de ViewHelpers? Debido a que su nombre no es el nombre típico de las clases (es decir, nombres singulares), puede ser que una clase no sea lo que necesita. – epidemian

+0

¡Gran respuesta abajo gracias! Acepto que los ayudantes generalmente se definen en un ámbito global. En este caso, mantengo una biblioteca de funciones en una clase ViewHelpers, instanciada como una propiedad de mi clase de controlador principal. Hay algunas funciones (por ejemplo, gestores de transición CSS End) que me gustaría suscribir varios oyentes en lugar de pasar una única devolución de llamada. Como ya estoy usando Backbone, pensé que subclase la "clase" del evento (objeto) para ese propósito. Lamento llegar tarde a esta respuesta, no estoy seguro de por qué no me notificaron hace meses. – benipsen

Respuesta

38

Eso es porque Backbone.Events no es una "clase", por lo que no se puede extender, es un "módulo" que se puede mezclar en otros objetos (consulte los documentos here). En términos de JavaScript que significa que no es Function, que se puede llamar como constructor (es decir, new Backbone.Events arrojará un error), es simplemente un objeto JS simple cuyas propiedades (métodos) se pueden asignar a otros objetos para convertirlos en despachadores de eventos.

En CoffeeScript, se pueden mezclar en el Backbone.Events en sus objetos cuando se crean:

class ViewHelpers 
    constructor: -> 
    _.extend @, Backbone.Events 

o simplemente puede extender el prototipo de la clase y evitar que esos métodos como (propias) propiedades de todos ViewHelpers casos:

class ViewHelpers 
    _.extend @prototype, Backbone.Events 

Estos dos enfoques deberían trabajar y dejar que se instancia y utilizar viewhelpers como distribuidores de sucesos:

vh = new ViewHelpers 
vh.on 'foo', -> alert 'bar' 
vh.trigger 'foo'​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ 
+6

'_ (@: :). Extender Backbone.Events' es una alternativa a' _.extend @prototype, Backbone.Events' que podría leer mejor (según la definición local de * better * por supuesto). –

+2

@muistooshort Yeap, y la alternativa totalmente opuesta a todo-el-camino-explícita a '@ ::' es, en este caso, 'ViewHelpers.prototype' (para cualquier persona que se pregunte = D). – epidemian

+1

Publicación muy útil, mucha información sobre cómo funciona el café y la columna vertebral para una respuesta tan corta. – Andrew

1

Hay otra manera (por lo @epidemian contestados), que no implica copiar Backbone.Events en un nuevo objeto de usar como su prototipo - en su lugar, utilice Object.create para crear un nuevo objeto de usar como su prototipo, utilizando como Backbone.Eventssu prototipo.

class ViewHelpers 
    @prototype = Object.create(Backbone.Events) 

Ahora ViewHelpers 'prototipo es un objeto nuevo, vacío cuyo prototipo es Backbone.Events. Puede definir métodos en el prototipo ViewHelpers 'sin afectar Backbone.Events, pero todos los métodos Backbone.Events están todavía disponibles para ViewHelpers, sin tener que copiarlos en un objeto nuevo. Esto no solo ahorra (una cantidad minúscula de) memoria, sino que si terminó agregando a Backbone.Events más tarde, todos los ViewHelpers verán el cambio.

Para esto, necesitará a browser that has ES5's Object.create function o an Object.create polyfill.

0

Para aprovechar la excelente respuesta por @epidemian me gustaría añadir a esto, es un poco de un truco, pero que le permite guardar la clase con la declaración extends según lo especificado en la pregunta (que le permite llamar a super sobre todo los métodos 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 

sería estupendo para trabajar la llamada _.extend en la función Events.constructor pero no podía hacer que funcione ...

Cuestiones relacionadas