前端的js上線的時候一般會使用打包工具處理(webpack,gulp,ugly.js 等)。這樣做有幾點作用。
可前端開發工作中多多少少,會需要看別人的js程式碼。可隨之而來的就是各種噩夢。eval,jsfuck,obfuscator等各種混淆方案就出來了。當然這種也在一定程度上保護了自己的程式碼。可是對於閱讀者來說,簡直是天書。關於混淆,以及反混淆等空了再寫部落格講解。不過最常見的還是簡化,簡化後的程式碼,往往第一步處理起來是進行格式化,然後邊看邊修改。其中非常大的工作量是調整程式碼結構。理清檔案的結構邏輯。比如下面的程式碼。
1 function _createClass(t, e, a) { 2 return e && _defineProperties(t.prototype, e), a && _defineProperties(t, a), t 3 }
其實閱讀這個程式碼有些複雜的,裡面既有邏輯運算,也有序列表示式,也有返回值。這個是否非常想處理為下面的結構:
1 function _createClass(t, e, a) { 2 if (e) { 3 _defineProperties(t.prototype, e); 4 } 5 if (a) { 6 _defineProperties(t, a); 7 } 8 return t; 9 }
這種程式碼結構就清晰多了。可是如何自動化處理那?手動修改一是慢,二是非常容易出錯,在著無法完成功能複用。遇到其他的程式碼任然需要重新修改。比如這個時候又來了這樣一段程式碼。
1 function m(t) { 2 var e = this.data.get("items"), 3 a = this.data.get("loop"), 4 n = e.length; 5 t < 0 ? a ? this.data.set("activeIndex", n - 1) : this.data.set("activeIndex", 0) : t >= n ? a ? this.data.set("activeIndex", 0) : this.data.set("activeIndex", n - 1) : this.data.set("activeIndex", t) 6 }
首先一行定義了多個變數,變數的名稱真想重新命名一下,把e重新命名為items,a重新命名為loop, 不過最後的巢狀多層的三元運算,直接讓人崩潰。忽然就想到多年前同事說過的一句話,程式設計師何必為難程式設計師。玩笑歸玩笑,不過還是要積極的心態面對技術挑戰不是。
首先是變數宣告表示式,一次宣告了三個變數。這種寫法其實程式設計師是比較排斥的,非常想一行寫一個。
1 function m(offset) { 2 var items = this.data.get("items"); 3 var loop = this.data.get("loop"); 4 var length = items.length; 5 if (offset < 0) { 6 if (loop) { 7 this.data.set("activeIndex", length - 1); 8 } else { 9 this.data.set("activeIndex", 0); 10 } 11 } else { 12 if (offset >= length) { 13 if (loop) { 14 this.data.set("activeIndex", 0); 15 } else { 16 this.data.set("activeIndex", length - 1); 17 } 18 } else { 19 this.data.set("activeIndex", offset); 20 } 21 }; 22 }
上面的程式碼就好看多了,基本的邏輯也可以看懂了。當時就想有沒有工具可以做這個,或者如何利用現在的gpt工具去美化一下那。後檢索了大量的資料,使用過市面的各種工具,發現還是自己寫比較合適。gpt美化後,會有明顯的程式碼邏輯錯誤。更重要的是有輸入限制。
寫一個js程式碼美化工具,多麼具有挑戰性。起碼要懂編譯原理,程式的語意和語法。於是買了很多關於編譯原理的書。看幾本後就上手了。結果寫的80%以上了後,因為各種事情一直耽擱著。最近終於完成了大部分。感興趣的朋友可以看下。
https://www.dejs.vip/javascript/beautify (目前仍有部分bug並且無法100%還原始碼的)
function justAFunction(){console.info("test");}
上面的程式碼簡化後可能變成:
1 function a(){console.info("test");}
如果僅從程式碼中是無法推斷出原來函數的名字的。不過可以根據文中語意去判定。但是大多時候,你是無法判定的。程式碼邏輯分析中加入人工智慧或者使用程式碼庫比對,有可能可以做到。不過這種複雜的程度過高了。
這個工具也許是前端,逆向或者爬蟲工作者的一個福音。也或許會給程式碼持有者帶來不安或者擔憂。如何判定工具,留給使用者自行判定吧。