javascript:编写可调用对象

时间:2015-10-13 00:57:04

标签: javascript

注意:我为这个例子大大简化了逻辑。请假设我需要所描述的功能,闭包等。

最近,我写了一堂课:

function Foo () {
    var self = this;
    self.number = 0;
    self.methodA = methodA;

    /////

    function methodA () {
        self.number++;
    }
}

然后,我决定要做以下事情:

function Bar() {
    Foo.call(this);

    this.methodA = methodA;

    var cleanFoo = new Foo();
    ////

    function methodA () {
        this.number = cleanFoo.methodA.call(this);
    }
}

Bar.prototype = Foo;
Bar.prototype.constructor = Bar;

基本上,我希望Bar继承Foo,覆盖methodA,但要覆盖Foo methodA来自被覆盖的Foo

我意识到,在当前状态下,我无法拨打methodA self,因为它正在引用Foo,当我打电话时它来自一个干净的对象,即使我传入了不同的上下文,也会引用干净的对象。

我决定解决这个问题的方法是像这样重写function Foo () { this.number = 0; this.methodA = methodA; ///// function methodA () { var self = this; //assume I need this closure in methodA for logic that has been edited out. self.number++; } }

methodB

然而,我意识到我想将Foo添加到调用methodA的{​​{1}}:

function Foo () {
    this.number = 0;
    this.methodA = methodA;

    /////

    function methodA () {
        var self = this; //assume I need this closure in methodA for logic that has been edited out.
        self.number++;
    }

    function methodB () {
            methodA();   
           return this.number;
        }
    }

但我意识到,当我这样做时,self中的methodA将是methodB。我通过将methodB中的调用更改为this.methodA()来解决此问题,这确保了methodA中的上下文是对象本身而不是方法B.

我说错了吗?这是构建类的方法,以便它的方法可以调用吗?我错过了一些明显的东西。

2 个答案:

答案 0 :(得分:3)

如果要从覆盖子类方法调用原型上定义的父方法,可以直接访问原型。

如果BarFoo的子类,那么您可以像这样调用方法的Foo版本:

Bar.prototype.methodB = function () {
    // call base class implementation
    Foo.prototype.methodB.call(this);
}

如果方法未在原型上定义但在构造函数中设置,则必须先保存先前对方法的引用,然后才能在派生构造函数中覆盖它。

function Bar() {
     Foo.call(this);

     var oldMethodB = this.methodB;
     this.methodB = function() {
         // call base class implementation
         oldMethodB.call(this);
     }
}

在调用基类方法时,您可以使用.apply()Extracting Raw JSON as String inside a Spray POST route来设置this的适当值。

我不确定这是否是您的混淆点,但请记住,派生类和基类实例只有一个this值。有些人感到困惑,认为对象的this组件与对象的Bar组件有不同的Foo。事实并非如此。它是一个对象,具有来自同一对象上每个类的属性。因此,当您想要使用适当的Foo值调用this方法时,可以使用来自适当调用的this方法的Bar值。

此外,这一行不正确:

Bar.prototype = Foo;

应该是:

Bar.prototype = Object.create(Foo.prototype);

答案 1 :(得分:0)

你走在正确的轨道上! jfriend00做得很好解释。无论如何,这是我的答案。

您有一个处理应用程序核心元素的父类(Foo)。假设您想为应用程序的特定部分增加一个数字,您可以创建另一个名为var Bar = Class.create({ initialize: function() { // initialize any variables this.foo = new Foo(); // call foo this.incrementFooNumber(); }, incrementFooNumber: function() { this.foo.incrementNumber(); } }); var Foo = Class.create({ initialize: function() { // initialize any variables var number = 0; // assign locally this.number = number; }, incrementNumber: function() { this.number++; } }); 的类。

看看它的外观如何:

Bar

您可以通过致电:var bar = new Bar();轻松启动Bar现在您可以看到我们发起BarFoo内部是我们在本地分配incrementFooNumber的地方实例,而不是调用incrementNumber调用Foo内的方法compactAndConvertToList : Array (Maybe String) -> List String 。{/ p>