我在高级模式下使用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;
}
};
答案 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.isAvailable
和frame.storeBack.LocalStore
现已分开。这是编译器命名空间展平的行为,如果发生。
您在将属性放入构造函数本身时遇到了麻烦 - 编译器对您可能不期望的类进行了大量优化。
检查调试输出和变量名称映射以确认。您可能必须删除闭包装函数才能在地图文件中查看实际名称。
答案 1 :(得分:1)
不确定你的后端究竟是什么...... 但是你不应该实例化它们吗?
var backends = { localStore : new frame.storeBack.LocalStore(),
mem: new frame.storeBack.Mem() };