18

我有 3 节课:

class A{
    DoStuff(){
        return "Called from A";
    }
}

class B extends A {

    constructor(){
        super();
        var baseDoStuff = super.DoStuff;
        this.DoStuff = function(){
            return baseDoStuff() + " and Called from B";
        }
    }
}

class C extends B { 
    constructor(){
        super();
        var baseDoStufffff = super.DoStuff;
        this.DoStuff = function(){
            return baseDoStufffff() + " and Called from C";
        }
    }
}

我希望 C 类的 DoStuff() 调用 B 的 DoStuff() (这反过来又会调用 A)。

但是,在 C 上调用 DoStuff() 仅返回“从 A 调用并从 C 调用”。我在这里做错了什么?这不应该也调用B的方法吗?

可以在这里找到一个工作示例:

例子

4

2 回答 2

23

每当您需要使用super使用类方法而不是类成员时:

class A{
    DoStuff(){
        return "Called from A";
    }
}

class B extends A {

    constructor(){
        super();      

    }   
    DoStuff (){
        return super.DoStuff() + " and Called from B";
    }
}

class C extends B { 
    constructor(){
        super();                
    }

    DoStuff(){
            return super.DoStuff() + " and Called from C";
    }
}

var c = new C();
console.log(c.DoStuff());

试试看(打印从 A 调用、从 B 调用和从 C 调用)

这是因为super转换为.prototypeiesuper.DoStuff()成为_super.prototype.DoStuff()并且唯一可用的东西.prototype是类方法。

更多:http ://basarat.github.io/TypeScriptDeepDive/#/super

于 2013-05-30T14:53:05.557 回答
8

JavaScript 并没有真正的方法。TypeScript 试图用熟悉的符号隐藏原型链的工作原理,但与所有抽象一样,它并不完美。原型链的要点是,当您调用c.DoStuff()它时,它会在 c 实例上查找 DoStuff,然后是原型 (C),然后是原型 (B),然后是原型 (A),然后是原型 (Object)。

这不仅适用于函数,还适用于您可能查找的任何成员。函数在 JavaScript 中并不是很特别,但讽刺的是,这正是它们强大的原因。

在你的 A 类中使用 TypeScript 的语法,你将一个函数 DoStuff 放在 A 的原型中。您调用 DoStuff 的 A 的每个实例都将在实例中查找它(并且可能无法在该实例中找到它)查看原型并查看您定义的函数。到目前为止,一切都很好。

然后你定义了一个扩展A的类B,所以原型链是B->A->Object。在 B 的构造函数中,您为每个实例上的 DoStuff 分配一个新的函数副本。(这会占用更多内存。)因此,当您构造一个新的 B 并在其上调用 DoStuff 时,那里有一个函数,而无需检查原型。所以这行得通。

现在你定义了一个扩展 B 的类 C,原型链是 C->B->A->Object。同样,C 的每个实例都会获得分配给 DoStuff 的函数的副本。但是在构造函数中,我们不是从 B 的实例中获取 DoStuff,而是从原型中获取它,并且我们没有将该函数直接添加到原型中。在那里找不到它,我们沿着原型链向上到 A.prototype 并从那里找到要使用的 DoStuff 成员。这就是 C 引用 A 的 DoStuff 的原因。

如果您执行以下操作,则可以使您的代码按预期工作:

class B extends A {
    constructor() {
        super();
    }
}
B.prototype.DoStuff = function () {
    return A.prototype.DoStuff() + " and Called from B";
}

但这只是愚蠢的。

于 2013-05-30T18:06:19.173 回答