为什么Closure Compiler不识别自执行匿名函数中的类型声明?

时间:2011-03-03 02:43:10

标签: javascript design-patterns google-closure-compiler jsdoc

当通过Closure Compiler运行一个相当大的库时,我收到了很多"Unknown type"警告,当我的类型在自执行匿名函数中声明时,它们似乎发生了。关于这一点没有什么奇特之处,但如果我将自执行函数剥离出来,那么类型声明似乎起作用(至少在这个简单的测试中)。

我不确定我的代码注释是否有问题,或者代码中是否有任何异常,但我认为这都是犹太教和模块化API的标准方法。

以下测试代码创建一个命名空间(只是一个普通的旧JS对象)并附加一个枚举(一个对象文字)和一个函数。

var mynamespace = {};
(function (mynamespace) {
    /**
     * Some enum.
     * @enum {number}
     */
    mynamespace.SomeEnum = {
        FOO: 1,
        BAR: 2
    };

    /**
     * Frazzle some type.
     * @param {mynamespace.SomeEnum} qux The type to frazzle.
     * @return {boolean} whether the operation succeeded.
     */
    mynamespace.frazzle = function(qux) {
        return true;
    }
}(mynamespace));

// call it
mynamespace.frazzle(mynamespace.SomeEnum.FOO);

看起来很好,对吧?闭包编译器错误:

[jscomp] Compiling 1 file(s) with 37 extern(s)
[jscomp] X:\dev\solclientjs\sdk\tools\jscomptest.js:14: WARNING - Parse error. Unknown type mynamespace.SomeEnum

[jscomp]      * @param {mynamespace.SomeEnum} qux The type to frazzle.

4 个答案:

答案 0 :(得分:3)

修改

原来的答案完全没了。

这肯定是编译器中的一个错误。我没有找到有关此问题的错误报告,但我发现两个错误报告似乎解决了此问题的反向(编译器应该抛出警告,但除非您打开匿名函数,否则它不会。)< / p>

http://code.google.com/p/closure-compiler/issues/detail?id=134

http://code.google.com/p/closure-compiler/issues/detail?id=61

在任何情况下,当与类型表达式一起使用时,它看起来像匿名函数。

答案 1 :(得分:3)

在您的示例中,参数“mynamespace”正在向“em> global mynamespace”对象传递“别名”。在全局对象(全局mynamespace)中使用别名(本地mynamespace)可防止对全局对象下的整个树进行优化。对于高级模式下的Closure Compiler,这是一个不好的想法。

在局部变量下定义的任何函数都是volatile。编译器不知道(没有深度代码流分析)本地“mynamespace”是全局“mynamespace”的别名。因此,它不会自动将您在局部变量下定义的任何内容与其别名的对象相关联。

正确的方法是:

选项#1,直接使用全局对象:

(function() {
    mynamespace.someEnum = ...
})();

选项#2,使用goog.scope别名(假设您使用的是高级模式):

goog.scope(function() {
    var somevar = mynamespace;

    (function() {
        somevar.someEnum = ...
    })();
});

这两个选项都可以为您提供所需的结果。但是,目前有没有方法可以通过参数将所需内容写入包装器闭包中。

答案 2 :(得分:1)

Closure Compiler在这里有所改进。要纠正上面的代码以便识别它,你需要做的唯一事情就是将命名空间声明为@const:

/ ** @const * / var mynamespace = {};

然后识别出类型。

答案 3 :(得分:0)

Closure Compiler不支持本地类型名称。名称必须是全局的,并且在函数“mynamespace”中是本地名称。