2013-04-08 11 views
6

Zbudowałem dużą aplikację wykorzystującą prototyp i dziedziczenie JavaScript. Ale trudno mi organizować mój kod. Na przykład mam karuzela klasa, która posiada wiele funkcji takich jak to:Porządkuj prototypowy javascript, jednocześnie zachowując odniesienie do obiektu i dziedziczenie.

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

chciałbym zorganizować mój kod tak:

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

Ale to spowoduje, że wartość „to” bycie Stracony. Mogę śledzić go za pomocą globalnej instancji, ale będzie to powodować problemy, gdy klasa jest dziedziczona na przykład w innym pliku mam coś takiego, aby zastąpić klasy nadrzędnej

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

Moja dziedziczenie odbywa się następująco:

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; 
}; 

Więc mogę zrobić:

BigCarousel.inheritsFrom(Carousel) 

Czy ktoś wie jak mogę obejść „to” wartości?

+0

Zobacz także [prototyp: głęboki zakres 'tego', aby uzyskać dostęp do kontekstu instancji] (http://stackoverflow.com/q/16502467/1048572) – Bergi

Odpowiedz

2

Można zrobić Controls klasy na jego własne:

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

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

nie pozwalają przesłonić realizację Controls chociaż. Z bardziej wstrzykiwania zależności chcesz uzyskać coś takiego:

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

To wydaje się najbardziej logiczną rzeczą do zrobienia, ale powiedzmy, że mam dużo funkcji, które zajmują się przedmiotami karuzelowymi, czy powinny również należeć do ich klasy? Na przykład 'Carousel.prototype.getItemsPassed = funkcja() {...} Carousel.prototype.setItemsPassed = funkcja() {...} Carousel.prototype.getThumbData = funkcja() {.. .} Carousel.prototype.setThumbData = function() {...} ' – Nima

+1

Być może w przypadku kontroli dekompozycja ma sens, ale z pewnością nie jest to coś, czego zawsze chcesz. Wystarczy postępować zgodnie z ogólnymi wytycznymi dotyczącymi OO i projektowania dziedziczenia. – Halcyon

1

Moja dziedziczenie odbywa się następująco:

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

Ouch. To nie jest dziedziczenie (z new BigCarousel instanceof Carousel), ale tylko kopiowanie właściwości. Może to ci wystarczy, ale powinieneś nazwać to mixin. Ponadto powinieneś avoid using new for inheritance.


Ale powoduje to wartość „to” giną. Jak mogę obejść to?

To niemożliwe, aby mieć this punkt do obiektu nadrzędnego o właściwościach zagnieżdżonych (tak długo, jak nie chcesz jawnie ustawić go za każdym razem). Masz tylko dwie możliwości:

  • zapomnę, i organizować swoje metody poprzedzając je (controlNext, controlBind, ...)
  • Daj każdej z karuzel własnej controls przedmiot. W przypadku dziedziczenia dodajmy na przykład instancje CarouselControls. To szczególnie dobrze pasuje, jeśli te elementy sterujące są zupełnie niezależne od karuzeli i nie potrzebują dostępu do karuzeli, do której są przymocowane wszędzie.Jeśli tak nie jest, nadal można przekazać odniesienie do karuzeli dominującej w ich konstruktora na przykład:

    this.controls = new CarouselControls(this); 
    

    także do dostosowywania elementów sterujących w różnych karuzel, można mieć do podklasy CarouselControls a także - albo przygotować swój obiekt Controls służyć do różnych karuzel w ogóle, tak że od BigCarousel można

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

Dziękuję za uwagę, wiedziałem o tym, ale płytka kopia działa dobrze na chwilę, nie mogłem zrobić wiele dziedziczenia prawidłowo jak: 'Karuzela.inheritsFrom (baza) Karuzela.inheritsFrom (obrazy)' – Nima

+0

OK, tak, dla dziedziczenia wielokrotnego musisz używać takich mixinów. Tylko ustawienie tej pojedynczej właściwości 'parent' nie ma wtedy sensu :-) – Bergi

0

można użyć .bind metodę funkcję.

W JavaScript funkcje dziedziczą z Object, więc mają własne metody. Jedną z tych metod jest .bind:

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

Również robisz dziedziczenia złego, we właściwy sposób z surowego JavaScript jest:

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

ChildClass.prototype= new ParentClass(); 

Następnie można po prostu zrobić to na konstruktora:

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

Ale muszę przyznać, że sugestia Frits jest lepsza, sprawić, by kontrolki były własną klasą i utworzyć instancję na konstruktorze Carousel odniesienie do twojej instancji Carousel (tego słowa kluczowego). Po prostu nie nazywaj tego ".ref", jest to mylące.

Powiązane problemy