Реализация наследования JavaScript Джона Резига: зачем «инициализировать»?

Я изучаю реализации Джона Резига OOO в JavaScript. Код выглядит так:

(function(){
    var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
    this.Class = function(){};
    Class.extend = function(prop) {
        var _super = this.prototype;
        initializing = true;
        var prototype = new this();
        initializing = false;
        for (var name in prop) {
            // ...
        }
        function Class() {
            if ( !initializing && this.init )
                this.init.apply(this, arguments);
        }
        Class.prototype = prototype;
        Class.prototype.constructor = Class;
        Class.extend = arguments.callee;
        return Class;
    };
})();

Проблема в следующем: почему мы используем здесь initializing?

Я предполагаю, что оператор var prototype = new this(); может быть асинхронным. Таким образом, когда вызывается new ChildClass(), инициализация (назначение properties прототипу ChildClass) может быть не выполнена. Но я совершенно не уверен, правильно это или нет.

После поиска я все еще не могу понять цель использования переменной initializing. Я обнаружил, что в этой статье есть некоторые пояснения, но я не мог понять: Понимание Джона Резига «Простое наследование JavaScript»

Может ли кто-нибудь подробно объяснить цель этого? Скажем, приведите несколько сценариев, когда код не работает без initializing?


Обновлять

Задача решена.

Я написал статью, чтобы записать подробности: Понимание "Простого наследования JavaScript" Джона Резига


person Joy    schedule 20.10.2015    source источник


Ответы (1)


function Class() {
    if ( !initializing && this.init )
        this.init.apply(this, arguments);
}

когда initializing истинно, вы «настраиваете» сам объект класса, поэтому вы не хотите вызывать метод экземпляра init, определенный каждым конкретным классом.

Вы можете сделать что-то вроде этого: var RedCoupe = Class.extend({ init: function () { this._type = 'coupe'; this._color = 'red'; }); var myCar = новый RedCoupe();

В этом случае вы хотите, чтобы new RedCoupe(); вызывал init, но не при вызове var RedCoupe = Class.extend({ ... });, имеет ли это смысл?

person Natural Lam    schedule 20.10.2015
comment
Спасибо. Обычно, когда выполняется Class.extend, initializing устанавливается в true, затем new, затем устанавливается в false. Если new всегда синхронизировано, когда оно достигает if ( !initializing && this.init ), значение initializing всегда равно false. Если это всегда false, зачем его использовать? - person Joy; 20.10.2015
comment
да, извините, я как бы сказал обратное. поэтому, когда инициализация имеет значение true, это означает настройку объекта класса, который new this() назначается прототипу класса, поэтому мы не должны вызывать метод экземпляра init. - person Natural Lam; 20.10.2015
comment
отредактировал исходный пост, так как вы указали на опечатку, спасибо~ - person Natural Lam; 20.10.2015
comment
Спасибо за вашу помощь. Но мой вопрос: обычно initializing всегда false, когда вызывается оператор if ( !initializing && this.init ), я прав? Если всегда false, зачем его использовать? - person Joy; 20.10.2015
comment
ооо, зачем его использовать, вы сделаете что-то вроде этого: var RedCoupe = Class.extend({ init: function () { this._type = 'coupe'; this._color = 'red'; }); var myCar = new RedCoupe(); В этом случае вам нужно new RedCoupe(); вызывать init, но не при вызове RedCoupe = Class.extend({ ... });, имеет ли смысл? - person Natural Lam; 20.10.2015
comment
добавил больше деталей в ответ - person Natural Lam; 20.10.2015
comment
I console.log последовательность выполнения. Когда код RedCoupe = Class.extend({ ... }); выполняется, он вызывает функцию init своего родительского класса, то есть Class (через new this()), а не функцию init RedCoupe. Функция init вызывается, когда new RedCoupe(). - person Joy; 20.10.2015
comment
О, я вдруг понял, что вы имеете в виду. Да, это имеет смысл. Большое спасибо! Я бы предложил вам обновить ответ, чтобы проиллюстрировать его более четко для справки других. - person Joy; 20.10.2015
comment
рад, что помогло. Хотя изучение основ JS — это здорово, если вы не в курсе, в ES6 есть некоторая встроенная поддержка объектно-ориентированного программирования (es6-features.org) Хотя он еще не полностью поддерживается всеми браузерами, многие люди используют транспиляторы, такие как babel (babeljs.io ), чтобы транспилировать его в ES5 на данный момент. - person Natural Lam; 20.10.2015