Странная проблема закрытия компилятора - PullRequest
1 голос
/ 25 марта 2011

Я использую Google Closure Compiler в расширенном режиме, и у меня странная проблема.Вот не скомпилированный код с возвращенным оператором log из скомпилированной версии:

goog.provide('frame.store');

goog.require('frame.storeBack.LocalStore');
goog.require('frame.storeBack.Mem');

frame.store = (function() {
    /** prioritised list of backends **/
    var backends = [
        frame.storeBack.LocalStore,
        frame.storeBack.Mem
    ];

    frame.log(backends); 
    // [function rc(){}, function tc(){this.q={}}]

    frame.log(frame.storeBack.LocalStore === backends[0]); 
    // true

    frame.log(frame.storeBack.LocalStore.isAvailable === backends[0].isAvailable); 
    // false

    frame.log(frame.storeBack.LocalStore.isAvailable);
    // function sc(){try{return"localStorage"in window&&window.localStorage!==k}catch(a){return l}}

    frame.log(backends[0].isAvailable);
    // undefined

    for (var i=0, len=backends.length; i<len; i++)
        if (backends[i].isAvailable())
            return new backends[i]();
    // Uncaught TypeError: Object function rc(){} has no method 'Ga'

    throw('no suitable storage backend');
})();

По какой-то причине статический метод isAvailable отсутствует, когда к LocalStore обращаются через массив backends, и присутствует, когда к нему обращаютсячерез его глобальное пространство имен.

Кто-нибудь может понять почему?

РЕДАКТИРОВАТЬ: для справки, вот объявление метода:

frame.storeBack.LocalStore.isAvailable = function() {
    try {
        return 'localStorage' in window && window['localStorage'] !== null;
    }catch (e) {
        return false;
    }
};

Ответы [ 2 ]

2 голосов
/ 26 марта 2011

Включите --debug true, чтобы проверить вывод и то, что frame.storeBack.LocalStore.isAvailable переименовано в.

Сбросить карту имен переменных, чтобы проверить, была ли frame.storeBack.LocalStore.isAvailable сведена.Закрывающий компилятор может сплющить frame.storeBack.LocalStore.isAvailable сначала в frame$storeBack$LocalStore$isAvailable, а затем переименовать все это в глобальную функцию "a" или что-то в этом роде.Это называется сплющиванием пространств имен.Проверьте выходные данные отладки, чтобы увидеть, было ли ваше объявление функции переименовано в:

$frame$storeBack$LocalStore$isAvailable$$ = function() {

В этом случае прямой вызов frame.storeBack.LocalStore.isAvailable() все равно вызовет упрощенную глобальную версию, здесь никаких проблем!Однако вы не можете объяснить, что isAvailable() существует в frame.storeBack.LocalStore (другом объекте) больше.В скомпилированном выводе frame.storeBack.LocalStore.isAvailable и frame.storeBack.LocalStore теперь разделены.Это поведение сплющивания пространства имен компилятора, , если это происходит .

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

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

1 голос
/ 25 марта 2011

Не уверен, что ваши бэк-энды точно ... Но разве вы не должны их создавать?

var backends = { localStore : new frame.storeBack.LocalStore(),
                 mem:         new frame.storeBack.Mem() };
...