2012-01-06 12 views
5

Sto sottoclassi il mio Backbone.View. Se, nella funzione di inizializzazione della super classe, scrivo:Perché il mio Backbone.View.constructor .__ super__ undefined se utilizzo _.bindAll (this)

_.bindAll (questo, 'molti', 'metodi');

E specificare i metodi che voglio associare a questo proposito, posso chiamare super-dalla sottoclasse via:

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

Ma, se nella classe super, io uso:

_.bindAll(this) 

invece, quando vado a chiamare super-dal mio sottoclasse,

this.constructor.__super__ 

non è definito. Qualche saggezza sul perché?

+0

non sicuro di quello che stai cercando di sottolineare, ho iniziato un jsfiddle per questo, ma si potrebbe completare con i tuoi problemi actuall con metodo bind della sottolineatura? http://jsfiddle.net/saelfaer/7fCbT/ – Sander

risposta

3

Perché non è sufficiente utilizzare questo per chiamare il super:

(sto separando a diverse linee di chiarimento, è possibile effettuare le chiamate in una sola riga)

var thisProto = Object.getPrototypeOf(thisInstance); 
var superProto = Object.getPrototypeOf(thisProto); 
superProto.superMethod.apply(thisInstance, [param1, param2]); 

Reference: GetPrototypeOf

1

I patch Backbone con getConstructor(), che restituisce il costruttore ed è immune a _.bindAll.

Usage:

this.getConstructor().__super__; 

Implementazione:

(function() { 
    var backboneExtend = Backbone.Model.extend; 
    var constructorExtend = function() { 
    var child = backboneExtend.apply(this, arguments); 
    child.prototype.getConstructor = function() { 
     return child; 
    }; 
    return child; 
    }; 
    Backbone.Model.extend = Backbone.Collection.extend = Backbone.Router.extend = Backbone.View.extend = constructorExtend; 
})(); 
2

Visto che ci sono solo soluzioni a questo problema, ma non le spiegazioni, ho intenzione di tentare di fornire una ...

Quando il metodo bindAll di Underscore viene invocato con il singolo argomento (l'oggetto), tutte le proprietà del tipo di funzione dell'oggetto non fanno più riferimento alla funzione originale ma un altro che corregge il contesto.

Poiché una delle proprietà dell'oggetto della funzione tipo è constructor, che è un riferimento alla funzione di costruzione Backbone (con la proprietà __super__), la proprietà verrà sovrascritta con una nuova funzione. Ciò significa che object.constructor non avrà più una proprietà __super__.

Per ovviare a questo problema ho usato la seguente funzione come alternativa al bindAll di sottolineatura:

function safeBindAll(obj) { 
    var funcs = Array.prototype.slice.call(arguments, 1); 

    if (funcs.length == 0) { 
     funcs = _.functions(obj); 
    } 

    _.each(funcs, function(f) { 
     var oldProps = obj[f]; 
     obj[f] = _.bind(obj[f], obj); 

     _.extend(obj[f], oldProps); 
    }); 

    return obj; 
} 

E 'quasi identico alla versione di sottolineatura, ma aggiunge le proprietà della funzione originale alla nuova funzione attraverso l'uso di _.extend() .

0

Sono nuovo a Backbone ma ho oltre 4 anni di esperienza con un altro framework che prevede anche il passaggio di un oggetto contenente metodi a un metodo di estensione, ma il problema è che questo non fornisce un controllo sufficientemente dettagliato su cui agire i metodi contenuti all'interno dell'oggetto passato.

Per ottenere più controllo è possibile invece passare una chiusura per estendere e la chiusura può restituire un oggetto. Questa tecnica in generale consente un controllo a grana più fine e un maggiore potenziale di sofisticazione e può essere sfruttata per risolvere il problema specifico.

All'interno della chiusura che restituisce i metodi, i metodi possono essere suddivisi in due grandi categorie:

  1. specifici Backbone, per esempio costruttore & inizializzare
  2. personalizzato, specifico per l'applicazione

Se torniamo i metodi personalizzati specifici per la nostra applicazione da loro oggetto separato, si può quindi utilizzare _.bind per "applicazione parziale" di _.bindAll solo a quei nomi di metodi personalizzati.

Mettere tutto insieme poi:

var foobar = Backbone.Model.extend(function() { 
    var foobarMethods = modelMethods(); 

    return _.extend({}, foobarMethods, { 
     constructor: function() { 
      _.bind(_.bindAll, this, _.keys(foobarMethods)); 
      // equivalent to _.bindAll(this, 'foo', 'bar') except that the above 
      // allow methods to be arbitrarily added or removed 
     }, 
     initialize : function() {}   
    }); 

    //It's possible to "mixin" these methods from another file 
    function modelMethods() { 
     return { 
      foo: function() {}, 
      bar: function() {}, 
     } 
    } 
}()); 
Problemi correlati