Установка C.prototype.constructor = C приводит к Stackru

Я изучал наследование js и в качестве учебного проекта я создаю собственную реализацию наследования базового класса. extend метод для создания новых классов. я использую C.prototype.constructor = C как говорит Стоян Сефанов, это приводит к переполнению стека, когда я пытаюсь вызвать конструктор базового класса.

Проблема в том, что второй уровень наследования продолжает вызывать свой собственный конструктор! Если я уберу эту строку, мое наследование, похоже, будет работать нормально.

Образец jsfiddle.

Вот моя реализация кода базового класса.

(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 ответа

Я провел немного времени, глядя на скрипку. Я не совсем уверен, что вы намереваетесь сделать код, но в строке 23 у вас есть:

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

который вызывает линию 35..

this._MyBaseCtor();

.. который вызывает линию 23, которая вызывает линию 35 и т. д.

Два предложения (простите, если вы хорошо знаете). Используйте оператор отладчика при отладке - обязательно. Рассмотрим библиотеку, например Underscore.js, если вы хотите использовать проверенное наследование в производственной среде.

Теперь, когда я понял проблему, решение было довольно простым. Я просто должен был сохранить ссылку на оригинальный ctor, прежде чем перезаписывать его, и вызывать его изнутри _MyBaseCtor, Вот обновленная скрипка.

Во-первых, удалите переопределение конструктора внутри определения 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);
};
Другие вопросы по тегам