1

我在高级模式下使用 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 不存在,而当通过其全局命名空间访问时,静态方法 isAvailable 存在。

谁能明白为什么?

编辑:作为参考,这里是方法声明:

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

2 回答 2

2

打开--debug true以检查您的输出以及frame.storeBack.LocalStore.isAvailable重命名为的内容。

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

例如,闭包编译器可能首先展平frame.storeBack.LocalStore.isAvailableframe$storeBack$LocalStore$isAvailable,然后将整个东西重命名为全局函数“a”或其他东西。这称为命名空间的扁平化。检查调试输出以查看您的函数声明是否已重命名为:

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

在这种情况下,frame.storeBack.LocalStore.isAvailable()直接调用还是会调用扁平化的全局版本,这里没有问题!但是,您不能再解释isAvailable()存在于frame.storeBack.LocalStore(另一个对象)中的那个。在编译后的输出中,frame.storeBack.LocalStore.isAvailableframe.storeBack.LocalStore现在分开了。这是编译器的命名空间展平的行为,如果发生的话。

您在将属性放入构造函数本身时遇到了麻烦——编译器对您可能没想到的类进行了很多优化。

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

于 2011-03-26T02:35:54.713 回答
1

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

var backends = { localStore : new frame.storeBack.LocalStore(),
                 mem:         new frame.storeBack.Mem() };
于 2011-03-25T15:49:39.223 回答