在Javascript

时间:2016-04-08 06:40:10

标签: javascript inheritance methods prototype extend

我有一些与“父子”相关的类(构造函数):

// Abstract root SuperClass

function SuperClass() {
    this.CLASS_ID = "SUPER-CLASS";
    throw new Error('Failed to instantiate abstract class' + this.CLASS_ID);
}

SuperClass.prototype.sayHello = function() {
    alert('Hello, world!');
};

// Absctract ClassA inherits from SuperClass
// inherit() and extend() are generic functions from the David Flanagan`s 
// brilliand book "Definitive Guide"

function ClassA() {
    this.CLASS_ID = "CLASS-A";
    throw new Error('Failed to instantiate abstract class' + this.CLASS_ID);
}

ClassA.prototype = inherit(SuperClass.prototype);

// Concrete ClassB inherits from ClassA

function ClassB(initData) {
    this.CLASS_ID = "CLASS-B";
}

ClassB.prototype = inherit(ClassA.prototype);

extend(ClassB.prototype, {
    constructor: ClassB,

    welcomeNewDay: function() {
        this.sayHello();
        this.doSomethingElse();
    },

    doSomethingElse: function(){
        alert('Jumping');
    }
});

var classB = new ClassB();
classB.welcomeNewDay();

如何在不重载的情况下正确扩展抽象.sayHello()的方法ClassA

我试图这样做:

extend(ClassA.prototype, {
    sayHello: function() {
        this.__proto__.sayHello();
        this.sing();
    },

    sing: function() {
        alert('Lalala');
    }
});

问题是.sing()被调用3次而不是1次。

如果我尝试:

this.__proto__.sayHello.call(this);

它抛出异常:

  

未捕获RangeError:超出最大调用堆栈大小

1 个答案:

答案 0 :(得分:1)

尝试访问初始类:

extend(ClassA.prototype, {
    sayHello: function() {
        SuperClass.prototype.sayHello.call(this);
        this.sing();
    },

    sing: function() {
        alert('Lalala');
    }
});

或只存储当前的sayHello()方法:

var initialSayHello = ClassA.prototype.sayHello;
extend(ClassA.prototype, {
    sayHello: function() {
        initialSayHello.call(this);
        this.sing();
    },

    sing: function() {
        alert('Lalala');
    }
});

您需要引用原始sayHello()方法。

  

未捕获RangeError:超出最大调用堆栈大小

抛出它是因为你实际上有一个无限递归,在方法中调用方法本身。