Strange Closure Compiler问题

时间:2011-03-25 15:28:39

标签: javascript google-closure-compiler google-closure

我在高级模式下使用Google的Closure Compiler,我遇到了一个奇怪的问题。这是未编译的代码,其中包含来自编译版本的返回日志语句:

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');
})();

由于某种原因,当通过后端数组访问LocalStore时,静态方法isAvailable不存在,并且当通过它的全局命名空间访问它时存在。

谁能明白为什么?

编辑:供参考,这是方法声明:

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

2 个答案:

答案 0 :(得分:2)

启用--debug true检查输出以及frame.storeBack.LocalStore.isAvailable重命名的内容。

转储变量名称映射以检查frame.storeBack.LocalStore.isAvailable是否已展平。

例如,Closure Compiler 可能先将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.isAvailableframe.storeBack.LocalStore现已分开。这是编译器命名空间展平的行为,如果发生

您在将属性放入构造函数本身时遇到了麻烦 - 编译器对您可能不期望的类进行了大量优化。

检查调试输出和变量名称映射以确认。您可能必须删除闭包装函数才能在地图文件中查看实际名称。

答案 1 :(得分:1)

不确定你的后端究竟是什么...... 但是你不应该实例化它们吗?

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