2013-04-08 3 views
6

Я создал большое приложение с использованием прототипа и наследования JavaScript. Но мне сложно организовать мой код. Например, у меня есть класс карусель, которая имеет множество функций, как это:Организовать прототип javascript при сохранении ссылки на объект и наследования

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

Я хотел бы организовать свой код так:

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

Но это вызовет значение «это» быть потерял. Я могу следить за его использованием глобального экземпляра, но это вызовет проблемы, когда класс наследуется, например, в другом файле у меня есть что-то вроде этого, чтобы переопределить родительский класс

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

Удел Мой делается так:

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

Так что я могу сделать:

BigCarousel.inheritsFrom(Carousel) 

кто-нибудь знает, как я могу работать вокруг «этого» значение?

+0

см. Также [прототип: глубокий охват 'this' для доступа к контексту экземпляра] (http://stackoverflow.com/q/16502467/1048572) – Bergi

ответ

2

Вы могли бы сделать Controls класс его собственной:

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

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

Это не позволяет переопределить реализацию Controls хотя. С дополнительной инъекции зависимостей вы получите что-то вроде:

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

Это кажется наиболее логичным, но можно сказать, что у меня есть много функций, которые занимаются карусели, если они тоже будут в своем классе? Например: 'Carousel.prototype.getItemsPassed = функция() {...} Carousel.prototype.setItemsPassed = функция() {...} Carousel.prototype.getThumbData = функция() {.. .} Carousel.prototype.setThumbData = function() {...} ' – Nima

+1

Возможно, в случае элементов управления разложение имеет смысл, но это, конечно же, не то, что вы всегда хотите. Просто следуйте общим принципам проектирования OO и наследования. – Halcyon

1

Удел Мой делается так:

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

Ой. Это не наследование (с new BigCarousel instanceof Carousel), а просто копирование свойств. Возможно, этого вам достаточно, но тогда вы должны называть его mixin. Кроме того, вы должны avoid using new for inheritance.


Но это приведет к тому, значение «это» теряется. Как я могу обойти это?

Это невозможно иметь this точку на родительский объект с вложенными свойствами (до тех пор, пока вы не хотите явно установить его каждый раз). У вас есть только два варианта:

  • Забудь, и организовать ваши методы, предваряя их (controlNext, controlBind, ...)
  • Дайте каждый из ваших каруселей своего собственного controls объекта. Например, для наследования сделайте их CarouselControls. Это особенно хорошо подходит, если эти элементы управления совершенно независимы от карусели и не нуждаются в доступе к карусели, к которой они привязаны повсюду.Если это не так, вы можете передать ссылку на родительской карусель в их конструкторы, например:

    this.controls = new CarouselControls(this); 
    

    Кроме того, для настройки элементов управления в различных каруселях, вы, возможно, придетесь подкласс CarouselControls, а также - или подготовить Controls объект, чтобы служить для различных каруселей в целом, так что с BigCarousel вы можете

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

Спасибо за головы, я знал об этом, но мелкая копия прекрасно работает на данный момент, я не мог сделать многократное наследование правильно: 'Carousel.inheritsFrom (Base) Carousel.inheritsFrom (Images)' – Nima

+0

OK, да, для множественного наследования вам нужно использовать такие микшины. Только установка этого одиночного «родительского» свойства не имеет смысла тогда :-) – Bergi

0

вы можете использовать .bind метод функции.

В функциях Javascript наследуется от Object, поэтому у них есть свои собственные методы. Одним из таких методов является .bind:

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

Также вы делаете наследование неправильно, правильный путь с сырым Javascript является:

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

ChildClass.prototype= new ParentClass(); 

Тогда вы можете просто сделать это на конструктор:

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

Но я должен сказать, что предложение Фритса лучше, сделайте элементы управления своим классом и создайте его на карусельном конструкторе, ссылку на ваш экземпляр Carousel (это ключевое слово). Просто не называйте это «.ref», это сбивает с толку.

Смежные вопросы