2011-09-21 13 views
-1

我一直在使用google閉包,試圖獲得大量的JavaScript編譯乾淨利用谷歌編譯器最小化。我碰到一個問題,但:Closure編譯器將閉包內部的定義視爲重定義

goog.provide('test'); 
goog.provide('test2'); 

/** 
* @constructor 
*/ 
test = function() { 
    this.x = 10; 
    this.y = 13; 
}; 

(function() { 
    /** 
    * @constructor 
    */ 
    test2 = function() { 
     this.x = 10; 
     this.y = 13; 
    }; 
})(); 

前者是好的。後者產生恆定的重定義錯誤:

JSC_CONSTANT_REASSIGNED_VALUE_ERROR. constant test2 assigned a value more than once at /home/hbrown/tmp/closure-test/foo.js line 16 : 10 
BUILD FAILED: 1 error(s), 0 warning(s) 

是否有某種方式來強制plovr /關閉編譯器允許這種構造?我環顧四周,一無所獲。


稍後:爲什麼關閉/ plovr認爲test2是一個常量?我懷疑當goog.provide被調用時,它與plovr/closure爲test2創建的命名空間有關。當它生成錯誤時,看到它正在處理的中間表單將會很好。

+0

Closure Compiler將全局級對象定義視爲與函數包裝器中定義的對象不同。當不在包裝封閉內部時,它會進行更多的優化。在你的情況下,它會崩潰goog.provide和test1的定義,所以你不會得到錯誤。 –

+0

是否有你在函數閉包中聲明全局構造函數test2的原因?它應該真的是var test2嗎?該格式有點混亂,似乎可能導致錯誤。我提到這一點是因爲解決這個尷尬的語法可能也會解決你的Closure編譯器問題。 –

+0

@Chris Moschini:是的,它確實是這樣的。 – hughdbrown

回答

0

雖然這只是一種猜測,但我仍將其作爲答案輸入,因爲評論對代碼來說很糟糕。

您是否嘗試過這樣的事情:

test2 = (function() { 
    /** 
    * @constructor 
    */ 
    function inner_test2() { 
     this.x = 10; 
     this.y = 13; 
    }; 

    // ... 

    return inner_test2; 
})(); 

我不認爲這是一個方便的重構,特別是如果該匿名函數又大又複雜,但它會很有趣(排序的)看看它是什麼讓編譯器感到困惑。

+0

我有〜900個使用這個習語的文件。我寧願找一些方法來配置closure/plovr,而不是在開發的這個階段改變大量的代碼。 – hughdbrown

+0

是的,正如我剛纔所說的,我只是在考慮實驗而已。如果沒有別的,它可能會幫助制定一個好的錯誤報告:-)我應該可能社區Wiki的「答案」。 – Pointy

0

取決於你爲什麼需要匿名函數,你可以嘗試用goog.scope功能關閉外

http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html

+0

我認爲公正地重申我之前對改變代碼的評論:「我有900個使用這個習慣用法的文件,我寧願找一些方法來配置closure/plovr,而不是在這裏改變大量代碼發展的階段「。除此之外,我不明白這是如何解決我的問題。在所有的封閉庫中都沒有使用goog.scope。 – hughdbrown

+0

如果您不想使用goog.scope或進行其他更改,則最好提交錯誤/功能請求:http://code.google.com/p/closure-compiler/issues/list 當我記得在立即調用匿名閉包時認識到類型聲明並使goog.provide的名稱空間不變是相對最近的變化。可能值得在樹頂部檢查編譯器的版本以查看是否有任何近期的行爲改變。 – John

0

申報測試2代替匿名函數,而不指定其爲:

var test2; 

(function() { 
    test2 = function(... 

我知道這不是一個像您希望的Closure Compiler配置更改,但它會改善代碼的可讀性並解決Closure Compiler的異議。

因爲它的歷史,使用Closure Compiler獲得的一點點實際上就是Google內部的Javascript代碼準則。因此,例如,您不能使用with語句,因爲這違反了政策,儘管您作爲公共用戶只是想縮小您的代碼,並且可能有一個允許貴公司的with語句的政策。

這就是說,我認爲在函數閉包中聲明全局並不是最好的做法(即使它是合法的Javascript)。編寫一個腳本可以很方便地尋找/(\w[\w\d-]+) = function/並在var文件的頂部用var聲明它。而且,這可能會導致所有修改的文件更容易被新的給定文件的編碼人員分析。

您剩下的選擇是修改開源的Closure Compiler代碼,以便警告這個違反Google JS政策的錯誤而不是錯誤。

相關問題