2012-06-17 11 views
15

Dostaję błąd:nie może przedłużyć backbone.events w coffeescript

Uncaught TypeError: Cannot read property 'constructor' of undefined 

Podczas deklarowania następujące klasy:

class ViewHelpers extends Backbone.Events 

mogę używać tej samej składni rozszerzenie Backbone.Router , widoki modelu itd. Oto skompilowany javascript którym pisałem w szybki dziennika, aby upewnić się Backbone.Events było

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

Więc linia przyczyną błędu jest

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

Jaka jest różnica __extends() metody, która będzie pracować dla Backbone.View a nie Backbone.Events?

+0

mam skomentował różnicę między Backbone.Events i inne obiekty szkieletu w odpowiedzi poniżej, ale chciałbym jako k: jaki jest cel ViewHelpers? Ponieważ jego nazwa nie jest typową nazwą klas (tj. Rzeczowników w liczbie pojedynczej), więc może się zdarzyć, że klasa nie jest tym, czego potrzebujesz. – epidemian

+0

Świetna odpowiedź poniżej dzięki! Zgadzam się, że pomocnicy są ogólnie definiowani w skali globalnej. W tym przypadku utrzymuję bibliotekę funkcji w klasie ViewHelpers, utworzoną jako własność mojej głównej klasy kontrolera. Istnieje kilka funkcji (na przykład obsługa przejściów CSS transitionEnd), które mogą chcieć subskrybować wiele detektorów zamiast przekazywania pojedynczego wywołania zwrotnego. Ponieważ używam już kręgosłupa, pomyślałem, że podklasuję w tym celu "klasę" zdarzenia (obiekt). Przykro mi, że spóźniłem się na tę odpowiedź, nie wiem, dlaczego nie dostałem powiadomienia kilka miesięcy temu. – benipsen

Odpowiedz

38

To dlatego, że Backbone.Events nie jest "klasą", więc nie można go rozszerzyć, jest to "moduł", który można połączyć z innymi obiektami (zob. Dokument here). W terminach JavaScript oznacza to, że nie jest to Function, który może być wywołany jako konstruktor (tzn. new Backbone.Events spowoduje błąd), to po prostu zwykły obiekt JS, którego właściwości (metody) można przypisać do innych obiektów, aby stały się nimi dyspozytorami zdarzeń.

W coffeescript można mieszać-w Backbone.Events do swoich obiektów podczas ich tworzenia:

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

Albo można po prostu rozszerzyć klasy prototyp i uniknąć tych metod jako (własnych) Właściwości wszystko ViewHelpers przypadki:

class ViewHelpers 
    _.extend @prototype, Backbone.Events 

te dwa podejścia powinny pracować i pozwalają instancji i używać ViewHelpers jak dyspozytorów wydarzenie:

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

'_ (@: :). Extend Backbone.Events' jest alternatywą dla' _.extend @prototype, Backbone.Events', który może być lepszy (w zależności od lokalnej definicji * lepszego * oczywiście). –

+2

@muistooshort Yeap, a polarną przeciwną, całkowicie jawną alternatywą dla '@ ::' jest w tym przypadku 'ViewHelpers.prototype' (dla każdego, kto zastanawia się = D). – epidemian

+1

Bardzo pomocny post, dużo wglądu w to, jak kawa i kręgosłup działają na tak krótką odpowiedź! – Andrew

1

Jest inny sposób (z tego co @epidemian odpowiedział), która nie wymaga kopiowania Backbone.Events do nowego obiektu użyć jako prototyp - zamiast używać Object.create aby utworzyć nowy obiekt do wykorzystania jako prototyp, stosując jako Backbone.Eventsjego prototyp.

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

Teraz ViewHelpers 'prototyp jest nowy, pusty obiekt, którego prototyp jest Backbone.Events. Możesz zdefiniować metody na prototypie ViewHelpers 'bez wpływu na Backbone.Events, ale wszystkie metody Backbone.Events są nadal dostępne dla ViewHelpers, bez konieczności kopiowania ich do nowego obiektu. To nie tylko oszczędza (niewielką ilość) pamięci, ale jeśli później dodałeś ją do Backbone.Events, wszystkie ViewHelpers s zobaczą zmianę.

Do tego potrzebne będzie albo a browser that has ES5's Object.create function, albo an Object.create polyfill.

0

Aby zbudować na doskonałą Odpowiedź @epidemian Dodam to, że jest to bit hack ale pozwala napisać klasę ze stwierdzeniem extends jak określono w pytaniu (co pozwala nazwać super na wszystko metody te 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 

byłoby miłe do pracy na wezwanie _.extend do funkcji Events.constructor ale nie mogłem zrobić to praca ...