设置C.prototype.constructor = C会导致StackOverflow

时间:2014-06-19 13:47:28

标签: javascript inheritance prototypal-inheritance

我一直在学习js继承,作为一个研究项目,我创建自己的继承实现,创建新类的基类extend方法。我使用C.prototype.constructor = C作为Stoyan Sefanov says to,但是当我尝试调用基类构造函数时,这会导致堆栈溢出。

问题是第二级继承继续调用它自己的构造函数!如果我删除该行,我的继承似乎工作正常。

jsfiddle sample

这是我对基类代码的实现。

(function(TestFramework, undefined) {
    TestFramework.Class = function() {};

    TestFramework.Class.extend = function(ctor) {
        var base = this;
        var derived = ctor;

        //Duplicate static property access to derived
        for (var property in base) {
            if (base.hasOwnProperty(property)) derived[property] = base[property];
        }

        //Create lightweight intermediate constructor to avoid calling the base constructor
        function lightweightCtor() { this.constructor = derived; };

        //Setup prototype chain
        lightweightCtor.prototype = base.prototype;
        derived.prototype = new lightweightCtor();
        derived.prototype._MyBase = lightweightCtor.prototype;
        derived.prototype._MyBaseCtor = function() {
            base.prototype.constructor.apply(this, arguments);
        };

        //Return derived class
        return derived;
    };

    TestFramework.Class.prototype.ClassName = "TestFramework.Class";
})(window.TestFramework);

2 个答案:

答案 0 :(得分:0)

我花了一点时间看着小提琴。我不完全确定您打算如何编写代码,但是在第23行,您有:

base.prototype.constructor.apply(this, arguments);

调用第35行。

this._MyBaseCtor();

..调用第23行,调用第35行等等。

两个建议(如果你很清楚,请原谅我)。调试时使用调试器语句 - 必不可少。如果要在生产环境中使用经过验证的继承,请考虑使用像Underscore.js这样的库。

答案 1 :(得分:0)

现在我理解了这个问题,解决方案非常简单。我只需要在覆盖之前存储对原始ctor的引用,并在_MyBaseCtor内调用它。这是the updated fiddle

首先,取出在lightweightCtor定义中的构造函数覆盖。

//Create lightweight intermediate constructor to avoid calling the base constructor
function lightweightCtor() {};

然后,添加一个新部分来配置构造函数。请注意检查base.__BaseCtor是否已配置,如果不是,则使用默认base.prototype.constructor

//Setup constructor references
derived.__BaseCtor = base.__BaseCtor || base.prototype.constructor;
derived.prototype.constructor = derived;
derived.prototype._MyBaseCtor = function() {
    derived.__BaseCtor.apply(this, arguments);
};