在保持对象引用和继承的同时组织javascript原型

Organize prototype javascript while perserving object reference and inheritance

本文关键字:javascript 原型 对象引用 继承      更新时间:2023-09-26

我使用JavaScript原型和继承构建了一个大型应用程序。但是我很难组织我的代码。例如,我有一个类carousel,它有许多函数,如下所示:

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

我可以这样写:

BigCarousel.inheritsFrom(Carousel)

有谁知道我怎么能围绕"this"值工作吗?

你可以让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));

我的继承是这样完成的:

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

哎哟。这不是继承(与new BigCarousel instanceof Carousel),但只是复制属性。也许这对你来说已经足够了,但是你应该把它叫做mixin。此外,您应该避免使用new进行继承。


但是这会导致"this"的值丢失。我该如何解决这个问题呢?

不可能让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
    

可以使用Function的。bind方法。

在Javascript函数继承自对象,所以他们有自己的方法。其中一个方法是。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 ",很容易混淆