奇怪的闭包编译器问题

发布于 2024-10-26 05:12:59 字数 1464 浏览 1 评论 0原文

我在高级模式下使用 Google 的闭包编译器,但遇到了一个奇怪的问题。以下是未编译的代码,其中包含从运行的编译版本返回的日志语句:

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 不存在,而当通过全局命名空间访问 LocalStore 时,静态方法 isAvailable 不存在。

谁能明白为什么吗?

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

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

I'm using Google's Closure Compiler in advanced mode, and I'm having a strange issue. Here is the uncompiled code, with returned log statement from the compiled version running:

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

For some reason the static method isAvailable is not present when LocalStore is accessed via the backends array, and is present when it's accessed via it's global namespace.

Can anyone see why?

EDIT: for reference, here is the method declaration:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

屌丝范 2024-11-02 05:12:59

打开 --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.isAvailableframe.storeBack.LocalStore 现在是分开的。这是编译器命名空间扁平化的行为(如果发生的话)。

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

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

Turn on --debug true to check your output and what frame.storeBack.LocalStore.isAvailable is renamed to.

Dump a variables name map to check whether frame.storeBack.LocalStore.isAvailable has been flattened.

For example, the Closure Compiler may flatten frame.storeBack.LocalStore.isAvailable first to frame$storeBack$LocalStore$isAvailable, then rename the whole thing to the global function "a" or something. This is called flattening of namespaces. Check the debug output to see whether your function declaration has been renamed to:

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

In such case, calling frame.storeBack.LocalStore.isAvailable() directly will still call the flattened global version, no prob here! However, you can't expact that isAvailable() exists in frame.storeBack.LocalStore (another object) any more. In the compiled output, frame.storeBack.LocalStore.isAvailable and frame.storeBack.LocalStore are now separated. This is the behavior of the compiler's namespace flattening, if it happens.

You're asking for trouble putting properties into a constructor function itself -- the compiler does a lot of optimizations on classes that you may not expect.

Check the debug output and variable names map to confirm. You may have to remove the closure wrapper function in order to see the actual names in the map file.

偏爱你一生 2024-11-02 05:12:59

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

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

Not sure what your back ends are exactly...
But shouldn't you instantiate them?

var backends = { localStore : new frame.storeBack.LocalStore(),
                 mem:         new frame.storeBack.Mem() };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文