簡體   English   中英

為什么Closure Compiler不識別自執行匿名函數中的類型聲明?

[英]Why doesn't Closure Compiler recognize type declarations inside a self-executing anonymous function?

當通過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.

編輯:

原來的答案完全沒了。

這肯定是編譯器中的一個錯誤。 我沒有找到有關這個問題的錯誤報告,但是我發現了兩個錯誤報告似乎解決了這個問題的反面(編譯器應該拋出警告,但除非你打開匿名函數,否則它不會發出警告)。

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

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

在任何情況下,當與類型表達式一起使用時,它看起來像匿名函數。

在您的示例中,參數“mynamespace”正在向全局 mynamespace對象傳遞“別名”。 在全局對象(全局mynamespace)中使用別名(本地mynamespace)可防止對全局對象下的整個樹進行優化。 對於高級模式下的Closure Compiler,這是一個不好的想法。

在局部變量下定義的任何函數都是volatile。 編譯器不知道(沒有深度代碼流分析)本地“mynamespace”是全局“mynamespace”的別名。 因此,它不會自動將您在局部變量下定義的任何內容與其別名的對象相關聯。

正確的方法是:

選項#1,直接使用全局對象:

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

選項#2,使用goog.scope別名(假設您使用的是高級模式):

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

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

這兩個選項都可以為您提供所需的結果。 但是,目前沒有辦法通過參數進入包裝器閉包。

Closure Compiler在這里有所改進。 要糾正上面的代碼以使其被識別,您唯一需要做的就是將名稱空間聲明為@const:

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

然后識別該類型。

Closure編譯器不支持本地類型名稱。 名稱必須是全局的,並且在函數“mynamespace”中是本地名稱。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM