Google Compiler не назначает пустые массивы переменным?

Так что я довольно новичок в использовании Google Compiler и столкнулся с несколькими проблемами. Во-первых, в моем предварительно обработанном коде я устанавливаю пустой массив для переменной, которая будет заполнена позже, но при компиляции она полностью удаляет переменную, так что она становится неопределенной при попытке использовать ее позже.

Вот код, который я немного изменил. Строка 19 заканчивается удалением, поэтому rowDivs отображается как неопределенное в строке 44:

/**
 * Equal Heights
 *
 * @see https://css-tricks.com/equal-height-blocks-in-rows/
 */
goog.provide('EqualHeights');

(function($) {

    // =  Equalize columns on load and resize
    equal_heights();

    $(window).resize(function() {
        equal_heights();
    })

    var currentTallest = 0;
    var currentRowStart = 0;
    var rowDivs = new Array();

    function setConformingHeight(el, newHeight) {

        // set the height to something new, but remember the original height in case things change
        el.data("originalHeight", (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight")));
        el.height(newHeight);
    }

    function getOriginalHeight(el) {

        // if the height has changed, send the originalHeight
        return (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight"));
    }

    function equal_heights() {

        // find the tallest DIV in the row, and set the heights of all of the DIVs to match it.
        $('[data-equalizer-watch]').each(function() {

            // "caching"
            var $el = $(this);
            var topPosition = $el.position().top;

            if (currentRowStart != topPosition) {

                // we just came to a new row. Set all the heights on the completed row
                for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest);

                // set the variables for the new row 
                rowDivs.length = 0; 

                // empty the array 
                currentRowStart = topPosition; 
                currentTallest = getOriginalHeight($el);
                rowDivs.push($el);
            } 
            else { 

                // another div on the current row. Add it to the list and check if it's taller
                rowDivs.push($el);
                currentTallest = (currentTallest < getOriginalHeight($el)) ? (getOriginalHeight($el)) : (currentTallest);
            }
        }); 

        // do the last row
        for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) { 
            setConformingHeight(rowDivs[currentDiv], currentTallest);

        }
    } 

})(jQuery);

Для настроек компилятора я использую следующие флаги. Обратите внимание, что я даже не использую уровень сложности продвинутой оптимизации:

--closure_entry_point main.js
--externs node_modules/google-closure-compiler/contrib/externs/jquery-1.9.js
--language_in ECMASCRIPTS5
--warning_level: VERBOSE

Я, наверное, упускаю что-то очевидное, но просто хочу встать на правильный путь. Благодарю.

1 ответ

В режиме простой компиляции локальные переменные минимизируются и потенциально удаляются, если не используются. Вероятно, происходит следующее: на основе указанной вами точки входа компилятор замыкания определяет, что rowDivs никогда не может использоваться.

Для исправления нужно сообщить компилятору замыкания больше информации.

(Отказ от ответственности: я никогда не использовал jquery, поэтому я могу быть не в курсе. Я также никогда не использовал узлы или модули, и есть специальные способы написания для тех, с которыми я не знаком.)

Одна вещь, чтобы попробовать это специальный флаг для jquery: --process_jquery_primitives см. https://github.com/google/closure-compiler/wiki/jQuery-Expansions

JQuery-1.9 Extern определяет $ как глобальная переменная, поэтому вам не нужно передавать ее в вашу функцию.

Вам может потребоваться указать closure-compiler для экспорта определенных вами функций. См. "Экспорт символов, которые вы хотите сохранить" в https://developers.google.com/closure/compiler/docs/api-tutorial3

Если вы открыты для использования "объектно-ориентированного стиля", вот несколько идей. Вероятно, есть способ написать свой код, не переходя на объектно-ориентированный стиль, но я недостаточно знаком с этим стилем, чтобы помочь вам.

(Я не знаю, как заставить jquery активироваться при запуске вашей программы, но я предполагаю, что это происходит где-то в вашем коде запуска.)

Похоже, вы разработали этот код, чтобы быть самореализующейся функцией, которая происходит всякий раз, когда вы говорите goog.require('EqualHeights'), Но вы на самом деле ничего не определяете для пространства имен EqualHeights. Может быть, это вместо:

goog.provide('EqualHeights');

/**
* @constructor
*/
EqualHeights = function() {
    this.currentTallest = 0;
    this.currentRowStart = 0;
    this.rowDivs = new Array();
};

/**
* @param {!Element} el
* @param {number} newHeight
*/
EqualHeights.prototype.setConformingHeight = function(el, newHeight) {

    // set the height to something new, but remember the original height in case things change
    el.data("originalHeight", (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight")));
    el.height(newHeight);
};

/**
* @param {!Element} el
* @return {number}
*/
EqualHeights.prototype.getOriginalHeight = function(el) {

    // if the height has changed, send the originalHeight
    return (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight"));
}

/**
* @return {undefined}
*/
EqualHeights.prototype.equal_heights = function() {

    // find the tallest DIV in the row, and set the heights of all of the DIVs to match it.
    $('[data-equalizer-watch]').each(function() {

        // "caching"
        var $el = $(this);
        var topPosition = $el.position().top;

        if (this.currentRowStart != topPosition) {

            // we just came to a new row. Set all the heights on the completed row
            for(currentDiv = 0 ; currentDiv < this.rowDivs.length ; currentDiv++) 
              setConformingHeight(this.rowDivs[currentDiv], this.currentTallest);

            // set the variables for the new row 
            this.rowDivs.length = 0; 

            // empty the array 
            this.currentRowStart = topPosition; 
            this.currentTallest = getOriginalHeight($el);
            this.rowDivs.push($el);
        } 
        else { 

            // another div on the current row. Add it to the list and check if it's taller
            this.rowDivs.push($el);
            this.currentTallest = (this.currentTallest < getOriginalHeight($el)) ? (getOriginalHeight($el)) : (this.currentTallest);
        }
    }); 

    // do the last row
    for (currentDiv = 0 ; currentDiv < this.rowDivs.length ; currentDiv++) { 
        setConformingHeight(this.rowDivs[currentDiv], this.currentTallest);

    }
} 

Тогда в вашем коде запуска есть это:

goog.require('EqualHeights');

var eh = new EqualHeights();

// =  Equalize columns on load and resize
eh.equal_heights();

$(window).resize(function(){eh.equal_heights();});

Мне неясно, что делает эта строка:

var $el = $(this);

Значение this должен быть EqualHeights объект внутри каждого метода. Вы можете использовать goog.bind функция (если она доступна для вас), чтобы убедиться, что this это то, что вы хотите, чтобы это было для этой функции.

Другие вопросы по тегам