2013-04-08 10 views
6

Ho creato un'applicazione di grandi dimensioni utilizzando il prototipo e l'ereditarietà di JavaScript. Ma sto facendo fatica a organizzare il mio codice. Per esempio io ho una giostra classe che ha molte funzioni come questo:Organizzare il prototipo javascript mantenendo il riferimento e l'ereditarietà dell'oggetto

Carousel.prototype.next = function() {...} 
Carousel.prototype.prev = function() {..} 
Carousel.prototype.bindControls = function() {..} 

Vorrei organizzare il mio codice come questo:

Carousel.prototype.controls = { 
    next: function() { ... } , 
    prev: function() { ... }, 
    bindControls: function() { .. } 
} 

Ma questo farà sì che il valore di "questo" essere perduto. Posso tenere traccia di esso utilizzando un'istanza globale, ma questo causerà problemi quando la classe è ereditata ad esempio in un altro file che ho qualcosa di simile per ignorare classe padre

BigCarousel.prototype.next = function() {...} 

mia eredità è fatto in questo modo:

Function.prototype.inheritsFrom = function (parentClass) { 
    if (parentClass.constructor === Function) { 
     //Normal Inheritance 
     this.prototype    = $.extend(this.prototype , new parentClass); 
     this.prototype.constructor = this; 
     this.prototype.parent  = parentClass.prototype; 
    } 
    else { 
     //Pure Virtual Inheritance 
     this.prototype = $.extend(this.prototype, parentClass); 
     this.prototype.constructor = this; 
     this.prototype.parent = parentClass; 
    } 
    return this; 
}; 

così posso fare:

BigCarousel.inheritsFrom(Carousel) 

qualcuno sa come posso risolvere il "questo" valore?

+0

vedere anche [prototype: ambito profondo di 'this' per accedere al contesto dell'istanza] (http://stackoverflow.com/q/16502467/1048572) – Bergi

risposta

2

Si potrebbe fare Controls una classe a sé stante:

var Controls = function (controllable_object) { 
    this.ref = controllable_object; 
}; 
Controls.prototype.next = function() { 
    this.ref.foo(); 
} 
// .. 

var Carousel = function() { 
    this.controls = new Controls(this); 
}; 
// .. 

Questo non consente di ignorare l'attuazione di Controls però. Con più iniezione di dipendenza si otterrebbe qualcosa come:

var Controls = function (controllable_object) { 
    this.ref = controllable_object; 
}; 
Controls.prototype.next = function() { 
    this.ref.foo(); 
} 
// .. 

var Carousel = function() { 
     this.controllers = []; 
    }; 
Carousel.prototype.addController = function (controller) { 
     this.controllers.push(controller); 
    }; 
// .. 

var carousel = new Carousel(); 
carousel.addController(new Controls(carousel)); 
+0

Questa sembra la cosa più logica da fare, ma diciamo che ho molte funzioni che trattano articoli di carosello, dovrebbero essere anche nella loro stessa classe? Per esempio: 'Carousel.prototype.getItemsPassed = function() {...} Carousel.prototype.setItemsPassed = function() {...} Carousel.prototype.getThumbData = function() {.. .} Carousel.prototype.setThumbData = function() {...} ' – Nima

+1

Forse, nel caso dei controlli la scomposizione ha senso ma non è certamente qualcosa che si desidera sempre. Basta seguire le linee guida generali per la progettazione OO e ereditarietà. – Halcyon

1

mia eredità è fatto in questo modo:

$.extend(this.prototype , new parentClass); 

Ouch. Questa non è ereditarietà (con new BigCarousel instanceof Carousel), ma copia semplicemente le proprietà. Forse questo è abbastanza per te, ma dovresti chiamarlo mixin. Inoltre, è necessario avoid using new for inheritance.


Ma questo farà sì che il valore di "questo" sta perdendo. Come posso aggirare questo?

E 'impossibile avere this punto per l'oggetto padre con proprietà nidificati (fino a quando non si vuole impostare in modo esplicito ogni volta). Hai solo due scelte:

  • Lascia perdere, e organizzare i tuoi metodi anteponendo loro (controlNext, controlBind, ...)
  • dare a ciascuno dei vostri caroselli proprio oggetto controls. Per ereditarietà, ad esempio, creale istanze CarouselControls. Questo si adatta particolarmente bene se questi controlli sono abbastanza indipendenti dalla giostra e non hanno bisogno di accedere al carosello a cui sono attaccati ovunque.Se non lo sono, è ancora possibile passare un riferimento al carosello genitore nella loro costruttore ad esempio:

    this.controls = new CarouselControls(this); 
    

    Inoltre, per personalizzare i controlli in diversi caroselli, potrebbe essere necessario creare una sottoclasse del CarouselControls, come pure - o preparare il vostro oggetto Controls a servire per diversi caroselli in generale, in modo che da BigCarousel si può

    Carousel.call(this); // make this a carousel 
    this.controls.activate({big: true, fast: false}); // or something 
    
+0

Grazie per l'avviso, ero a conoscenza di questo, ma la copia superficiale funziona bene per il momento, non potrei fare un'eredità multipla correttamente come: 'Carousel.inheritsFrom (Base) Carousel.inheritsFrom (Immagini)' – Nima

+0

OK, sì, per ereditarietà multipla è necessario utilizzare tali mixaggi. Solo l'impostazione di quella singola proprietà 'parent' non ha senso quindi :-) – Bergi

0

È possibile utilizzare il metodo .bind della Funzione.

In Javascript, le funzioni ereditano da Object, quindi hanno i propri metodi. Uno di questi metodi è .bind:

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

Inoltre si sta facendo eredità sbagliato, nel modo giusto con Javascript prima è:

ChildClass= function() { 
    ParentClass.apply(this, arguments); //calling parent constructor 
    //constructor 
}; 

ChildClass.prototype= new ParentClass(); 

Poi si può semplicemente fare questo sul vostro costruttore:

Courossel= function() { 
    ParentClass.apply(this, arguments); //calling parent constructor 
    this.controls.next.bind(this); 
    this.controls.prev.bind(this); 
    this.controls.bindControls.bind(this); 
} 

Ma devo dire che il suggerimento di Frits è migliore, rendere i controlli propri della classe e istanziarlo sul costruttore di Carousel che passa un riferimento all'istanza di Carousel (la parola chiave this). Basta non chiamarlo ".ref", è confuso.

Problemi correlati