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

IT技术 javascript oop javascript-objects
2021-01-19 21:31:03

我已经使用 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;
};

所以我可以这样做:

BigCarousel.inheritsFrom(Carousel)

有谁知道我该如何解决“这个”值?

3个回答

你可以自己创建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));
也许,在控件的情况下,分解是有道理的,但这肯定不是您一直想要的。只需遵循面向对象和继承设计的一般准则即可。
2021-03-12 21:31:03
这似乎是最合乎逻辑的事情,但是假设我有很多处理轮播项目的功能,他们也应该在自己的class中吗?例如: Carousel.prototype.getItemsPassed = function () {...} Carousel.prototype.setItemsPassed = function () {...} Carousel.prototype.getThumbData = function () {...} Carousel.prototype.setThumbData = function () {...}
2021-03-22 21:31:03

我的继承是这样完成的:

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

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


但这会导致“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
    
好的,是的,对于多重继承,你需要使用这样的 mixin。只设置那个单一的parent属性是没有意义的:-)
2021-03-10 21:31:03
感谢您的提醒,我知道这一点,但目前浅拷贝工作正常,我无法正确地进行多重继承,例如: Carousel.inheritsFrom(Base) Carousel.inheritsFrom(Images)
2021-04-02 21:31:03

您可以使用 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 实例(this 关键字)的引用的 Carousel 构造函数上实例化它。只是不要称它为“.ref”,这很令人困惑。