Organize o protótipo do javascript enquanto mantém a referência e a inheritance do object

Eu construí um grande aplicativo usando protótipo de JavaScript e inheritance. Mas estou tendo dificuldade em organizar meu código. Por exemplo, eu tenho um carrossel de class que tem muitas funções como esta:

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

Eu gostaria de organizar meu código assim:

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

Mas isso fará com que o valor de “isso” seja perdido. Eu posso acompanhar isso usando uma instância global, mas isso vai causar problemas quando a class é herdada, por exemplo, em outro arquivo eu tenho algo parecido com isso para replace a class pai

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

Minha inheritance é feita assim:

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

Então eu posso fazer:

 BigCarousel.inheritsFrom(Carousel) 

Alguém sabe como posso trabalhar em torno do valor “this”?

Você poderia fazer do Controls uma class própria:

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

Isso não permite que você sobrescreva a implementação dos Controls . Com mais injeção de dependência, você teria algo como:

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

Minha inheritance é feita assim:

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

Ai Isso não é inheritance (com a new BigCarousel instanceof Carousel ), mas apenas copiando as propriedades. Talvez isso seja o suficiente para você, mas então você deve chamá-lo de mixin . Além disso, você deve evitar o uso de new para inheritance .


Mas isso fará com que o valor de “isso” seja perdido. Como posso contornar isso?

É impossível ter this ponto para o object pai com propriedades aninhadas (contanto que você não queira explicitamente defini-lo toda vez). Você tem apenas duas opções:

  • Esqueça e organize seus methods prefixando-os ( controlNext , controlBind ,…)
  • Dê a cada um de seus carrosséis seu próprio object de controls . Para inheritance, crie instâncias de CarouselControls por exemplo. Isso se encheckbox especialmente bem se esses controles forem independentes do carrossel e não precisarem acessar o carrossel ao qual estão conectados em todos os lugares. Se não estiverem, você ainda pode passar uma referência ao carrossel pai em seu construtor, por exemplo:

     this.controls = new CarouselControls(this); 

    Além disso, para personalizar os controles em carrosséis diferentes, você pode ter que subclassificar os CarouselControls também – ou você prepara seu object Controls para servir para diferentes carrosséis em geral, de modo que a partir de BigCarousel você pode

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

Você pode usar o método .bind da function.

Em funções JavaScript herdam de Object, então eles têm seus próprios methods. Um desses methods é .bind:

https://developer.mozilla.org/pt-BR/docs/JavaScript/Reference/Global_Objects/Function/bind

Além disso, você está fazendo inheritance errado, o caminho certo com o Javascript em bruto é:

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

Então você pode simplesmente fazer isso em seu construtor:

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

Mas devo dizer que a sugestão de Frits é melhor, faça os controles de sua própria class e instancie-a no construtor Carousel passando uma referência para sua instância Carousel (a palavra-chave this). Só não chame isso de “.ref”, é confuso.