2012-06-17 12 views
15

sto ottenendo l'errore:non può estendere backbone.events in CoffeeScript

Uncaught TypeError: Cannot read property 'constructor' of undefined 

Quando si dichiara la seguente classe:

class ViewHelpers extends Backbone.Events 

posso utilizzare la stessa sintassi di estendere Backbone.Router , Vista, modello ecc Ecco la javascript compilato, che ho scritto in un registro rapido per assicurarsi che Backbone.Events c'era

__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); 

Così la linea che causa l'errore è

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

Qual è la differenza __extends() metodo che avrebbe funzionato per Backbone.View e non Backbone.Events?

+0

ho commentato la differenza tra Backbone.Events e altri oggetti Backbone in una risposta di seguito, ma, mi piacerebbe come k: qual è lo scopo di ViewHelpers? Perché il suo nome non è il nome tipico per le classi (cioè nomi singolari), quindi potrebbe essere il caso che una classe non sia ciò di cui hai bisogno. – epidemian

+0

Ottima risposta qui sotto grazie! Sono d'accordo che gli aiutanti siano generalmente definiti in un ambito globale. In questo caso gestisco una libreria di funzioni in una classe ViewHelpers, istanziata come una proprietà della mia classe di controller principale. Ci sono alcune funzioni (ad esempio, i gestori di transizione CSSEnd) che potrei voler sottoscrivere più listener invece di passare un singolo callback. Dal momento che sto già usando Backbone ho pensato di creare una sottoclasse dell'Evento "class" (oggetto) per quello scopo. Mi dispiace di essere in ritardo su questa risposta, non sono sicuro del motivo per cui non sono stato avvisato mesi fa. – benipsen

risposta

38

Questo perché Backbone.Events non è una "classe", quindi non può essere esteso, è un "modulo" che può essere inserito in altri oggetti (vedere i documenti here). In termini JavaScript, ciò significa che non è un Function, che può essere chiamato come costruttore (ad esempio, new Backbone.Events genererà un errore), è semplicemente un oggetto JS le cui proprietà (metodi) possono essere assegnate ad altri oggetti per renderli dispatcher di eventi.

In CoffeeScript, potete mescolare-in Backbone.Events nei vostri oggetti quando vengono creati:

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

Oppure si può semplicemente estendere il prototipo di classe ed evitare di avere quei metodi come (proprio) proprietà di tutti ViewHelpers casi:

class ViewHelpers 
    _.extend @prototype, Backbone.Events 

Questi due approcci dovrebbero lavorare e lasciare che si crea un'istanza e utilizzare ViewHelpers come dispatcher di eventi:

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

'_ (@: :). Estensione Backbone.Events' è un'alternativa a' _.extend @prototype, Backbone.Events' che potrebbe leggere meglio (a seconda della definizione locale di * better * ovviamente). –

+2

@muistooshort Yeap, e l'alternativa polare opposta a "@ ::" è, in questo caso, "ViewHelpers.prototype" (per chiunque si chiede = D). – epidemian

+1

Post molto utile, molte informazioni su come Coffee e Backbone funzionano per una risposta così breve! – Andrew

1

C'è un altro modo (da quello che @epidemian risposto), che non comporta la copia di Backbone.Events in un nuovo oggetto da utilizzare come prototipo - Al contrario, utilizzare Object.create per creare un nuovo oggetto da utilizzare come prototipo, utilizzando come Backbone.Eventsil suo prototipo.

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

Ora ViewHelpers 'prototipo è un nuovo, oggetto vuoto il cui prototipo è Backbone.Events. È possibile definire i metodi sul prototipo ViewHelpers senza interessare Backbone.Events, ma tutti i metodi Backbone.Events sono ancora disponibili per ViewHelpers, senza doverli copiare in un nuovo oggetto. Questo non solo salva (una quantità minuscola di) memoria, ma se hai finito per aggiungere a Backbone.Events in seguito, tutti i ViewHelpers s vedrebbero la modifica.

Per questo, è necessario a browser that has ES5's Object.create function o an Object.create polyfill.

0

Per sfruttare l'eccellente risposta di @epidemian, aggiungerei questo, è un po 'un trucco ma consente di scrivere la classe con la frase extends come specificato nella domanda (che consente di chiamare super su tutti i Backbone.Events metodi):

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 

sarebbe pulito per lavorare la chiamata _.extend nella funzione Events.constructor ma non ho potuto farlo funzionare ...