我已经使用JavaScript原型和继承功能构建了一个大型应用程序。
但是我很难组织代码。
例如,我有一个类轮播,它具有许多类似这样的功能:

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


我想这样组织我的代码:

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


但是这将导致“ this”的值丢失。我可以使用全局实例来跟踪它,但是例如在继承该类时,这会引起问题。在另一个文件中,我有类似这样的东西来覆盖父类>我的继承是这样完成的:

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


有人知道吗如何解决“ this”值?

评论

另请参见原型:深入了解实例上下文的上下文

#1 楼

您可以使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));


评论


这似乎是最合乎逻辑的事情,但是可以说我有很多处理轮播项目的功能,它们也应该属于自己的班级吗?例如:Carousel.prototype.getItemsPassed = function(){...} Carousel.prototype.setItemsPassed = function(){...} Carousel.prototype.getThumbData = function(){...} Carousel.prototype.setThumbData =函数(){...}

–尼玛
13年4月8日在17:26



也许,对于控件而言,分解是有意义的,但肯定不是您一直想要的。只需遵循面向对象和继承设计的一般准则即可。

–太平
13年4月8日在18:40

#2 楼


我的继承是这样完成的:

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



很好。这不是继承(使用new BigCarousel instanceof Carousel),而只是复制属性。也许这对您来说已经足够了,但是您应该将其称为mixin。另外,您应该避免使用new进行继承。



但这会导致丢失“ this”的值。我该如何解决?



不可能this指向具有嵌套属性的父对象(只要您不想每次都明确地设置它)。您只有两种选择:


忘记它,并通过给它们加上前缀(controlNextcontrolBind…)来组织您的方法

让每个轮播都自己拥有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




评论


谢谢您的注意,我已经意识到了这一点,但目前浅表副本可以正常工作,我无法正确进行多重继承,例如:Carousel.inheritsFrom(Base)Carousel.inheritsFrom(Images)

–尼玛
13年4月8日在17:22



好的,是的,对于多重继承,您需要使用此类mixin。只有设置单个父属性才没有意义:-)

–贝尔吉
13年4月8日在17:34

#3 楼

您可以使用Function的.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);
}


但是我不得不说Frits建议更好,使控件成为自己的类,并在Carousel构造函数上实例化它,传递对您的Carousel实例的引用(this关键字)。只是不要称它为“ .ref”,这很令人困惑。