2011-07-04 111 views
1

我遇到了谷歌封閉JavaScript編譯器與高級優化問題。由於文檔建議,爲了保持出口的Javascript我做這樣的事情:谷歌封閉編譯器的高級優化不優化一些變量

var myClass = function() { 
    this["myFunc"] = this.myFunc; 
    this["myFunc2"] = this.myFunc2; 
}; 
window["myClass"] = myClass; 

myClass.prototype = { 
    myFunc: function() { alert("myFunc"); }, 
    myFunc2: function() { alert("myFunc2"); } 
}; 

的問題是,有時,無論出於何種原因,myFuncmyFunc2沒有得到縮短,我看到這樣的代碼在最後輸出:

x.myFunc=x.myFunc;x.myFunc2=x.myFunc2; 

這顯然不太理想。

我該如何防止這種情況發生?


進一步的實驗已經表明,有一定的關鍵字,例如'get'不會被編譯。

var myClass = function() { 
    this["get"] = this.get; 
    this["myFunc2"] = this.myFunc2; 
}; 
window["myClass"] = myClass; 

myClass.prototype = { 
    get: function() { alert("myFunc"); }, 
    myFunc2: function() { alert("myFunc2"); } 
}; 

編譯成

function a() { 
    this.get = this.get; 
    this.myFunc2 = this.a 
} 
window.myClass = a; 
a.prototype = {get:function() { 
    alert("myFunc") 
}, a:function() { 
    alert("myFunc2") 
}}; 

我仍然不知道,雖然是什麼導致了它。

回答

4

我不能重複你的問題。如果我去http://closure-compiler.appspot.com/home和編譯如下:

// ==ClosureCompiler== 
// @compilation_level ADVANCED_OPTIMIZATIONS 
// @output_file_name default.js 
// ==/ClosureCompiler== 

var myClass = function() { 
    this["myFunc"] = this.myFunc; 
    this["myFunc2"] = this.myFunc2; 
}; 
window["myClass"] = myClass; 

myClass.prototype = { 
    myFunc: function() { alert("myFunc"); }, 
    myFunc2: function() { alert("myFunc2"); } 
}; 

然後我得到以下結果:

function a(){this.myFunc=this.a;this.myFunc2=this.b}window.myClass=a;a.prototype={a:function(){alert("myFunc")},b:function(){alert("myFunc2")}}; 

的屬性被重新命名,符合市場預期。

至於你的第二個例子,它與Closure Compiler概念有關,如externsextern是一個符號,它將在JavaScript將運行的環境中預定義,例如在Web編程的情況下爲windowdocument。由於這些名稱在環境中已修復,因此編譯器無法修改這些名稱。

如果你看一下DEFAULT_EXTERNS_NAMES列表CommandLineRunner.java,你會看到從externs文件夾中的文件列表。這些文件的內容定義了編譯器知道的extern(你也可以添加你自己的extern)。 webgl.jsw3c_indexeddb.js都定義了一個名爲get(分別爲WebGLContextAttributesIDBObjectStore)的屬性。默認情況下,編譯器不知道myClass中的this的類型,因此就其所知,this可能指的是WebGLContextAttributesIDBObjectStore的實例,在這種情況下,重命名get將不安全。

通過使用類型註釋(如@constructor)組合和編譯器選項,例如ambiguatePropertiesdisambiguateProperties,編譯器可以確定this總是引用的myClass新實例及其所有引用重命名爲get一致。您可以在關閉:權威指南的第14章閱讀關於這些編譯器優化的更多信息。

+0

請參閱更新。 –

+0

我擴展了我的答案以解決您的更新。 – bolinfest

+0

我應該使用哪些註釋? –

0

原因是,對於ADVANCED_OPTIMIZATIONS,GCC將myObject [「a」]視爲與myObject.a不同。請嘗試以下操作:

var myObject = {}; 
myObject.attr1 = 3; 
myObject["attr2"] = 4; 
window["myObject"] = myObject; 

它將編譯到這一點,與ADVANCED_OPTIMIZATIONS:

window.myObject={a:3,attr2:4}; 

我想你會看到你現在需要做的事情。

+0

不,我明白,這就是爲什麼我在做'this [「xyz」] = this.xyz'。這與'window [「myObject」] = myObject'類似,除非我錯過了一些東西。 –

1

example here,它看起來像你需要明確出口原型方法構造之外:

var myClass = function() {}; 
myClass.prototype = { 
    myFunc: function() { alert("myFunc"); }, 
    myFunc2: function() { alert("myFunc2"); } 
}; 

window["myClass"] = myClass; 
myClass.prototype["myFunc"] = myClass.prototype.myFunc; 
myClass.prototype["myFunc2"] = myClass.prototype.myFunc2; 

這似乎是工作爲標榜,但它似乎是一個奇怪的優化,我(全部重複「原型」引用增加了很多字節):

function a(){}a.prototype={a:function(){alert("myFunc")}, 
b:function(){alert("myFunc2")}}; 
window.myClass=a; 
a.prototype.myFunc=a.prototype.a; 
a.prototype.myFunc2=a.prototype.b;