一般咱們在作項目的時候通常會出現這樣的一種狀況。html
<script> // a.js var varity=1; function changeHTML(){ //define function changeHTML } function decodeHTML(){ // define function decodeHTML } //……………… </script>
main.html的引入前端
<html> <body></body> <script src="a.js"></script> </html>
這個按照咱們正常的寫法上面來講是沒有什麼問題的,至少在使用上面沒有問題,可是卻存在一些隱患node
1. 假設後來有A同事須要添加一個方法叫作decodeString來處理string文本,B同事若是也要添加一個相似的方法,那麼就不可以使用decodeString來命名,除此以外這樣的函數定義也會直接把函數暴露到全局中。瀏覽器
2. 變量也會被散亂分佈到全局變量中,後續變量命名就會有命名衝突的隱患緩存
3. 若是是函數與函數之間的依賴關係比較難維護等問題服務器
對於這樣的一種狀況最開始谷歌的YUI提出的解決方案是與PHP,JAVA的解決方案類似就是添加一個命名空間。閉包
上面的代碼咱們能夠這樣的去編寫。模塊化
<script> // a.js // 變量 var variable={};//全局中只有惟一的一個variable,用來保存全部的變量 variable.varity=1; // 方法 var methods={};//全局中只有惟一的一個methods,用來保存全部的方法
var methods.common={}; methods.common.changeHTML=function(){ //define function changeHTML
alert(1);
} methods.common.decodeHTML = function () { //define function decodeHTML } </script>
咱們發現這樣的基本上面的這種方法是能夠解決一些沒必要要的衝突的(除非你是想給本身挖坑),假如咱們要添加一個關於用戶登陸的方法,咱們能夠這樣寫。函數
methods.users = {}; methods.users.login=function(str){ console.log(str); } methods.users.login("this is a test");
這樣去管理方法和變量雖然相比於第一種方法來講能夠有效的解決衝突,可是也是存在以下的一些問題:測試
1. 若是咱們要調用這個簡單的login方法,咱們會發現須要書寫一大串的前綴(methods.users.login)。代碼編寫風格不簡潔
2. 變量雖然是能夠有效的管理,可是確實沒有解決讀寫的控制,特別是若是團隊的人較多的話,容易發生誤操做,因此應該進行讀寫分離。
其實上面對變量的管理已經比較有效了,但只是缺乏讀寫的控制,容易發生誤操做,因此參照ES6的作法,從新編寫了一個getter方法和setting方法來獲取參數。
var val=function(){ var that=this; var variable={}; variable.varity=1; var returnVal={}; this.isString=function(str){ try { if (typeof str !== "string") { throw "TypeErr"; }else{ return true; } } catch (e) { if (e == "TypeErr") { return false; } } } returnVal.getter=function(str){ var isStr=that.isString(str); if(isStr){ return variable[str]; }else{ console.error("input type must string!!!!!"); } } returnVal.setter=function(key,value){ var isStr=that.isString(key); if(isStr){ if(variable[key]==undefined){ eval(variable[key]); } variable[key]=value; }else{ console.error("input type must string!!!!!"); } } return returnVal; }
運行代碼測試:
var val= val();//初始化方法 console.log(val.getter("varity"));// 1 val.setter("va222rity",3);//不存在從新添加並賦值 console.log(val.getter("va222rity")); // 3
如今這樣寫變量就不容易發生誤操做了(讀寫已經分離),也不會把變量泄漏到全局中去。
上面的函數就是對閉包的一個實際的應用。具體不懂的能夠自行百度閉包的知識(具體還能夠實現的更加的簡潔,在這裏不累贅)。
變量相關的優化方案咱們已經說了,咱們接下來講一說關於函數模塊化的應用。
模塊化最先是由node.js提出來的一種規範,具體的實現是CommonJS
可是因爲服務器端與瀏覽器端的不一樣,不一樣之處主要表如今服務器端加載文件是經過緩存讀取本地文件的形式來實現的,因此加載的時間能夠忽略不計,可是在瀏覽器端(前端)卻不是這樣的,每一個文件都是經過HTTP請求從服務器中下載而來,因此中間會產生必定的加載時間,因此瀏覽器端和服務器端你是不一樣的。
採用的方式是按需加載,也就是說何時須要就何時加載這個文件進來
共同點:都是實行對代碼的預先加載
異同點:RequireJS提出的觀點是預先加載並執行[早期],SeaJS提出的觀點是預先加載,按需執行。
相比之下,做者更傾向於RequireJS的實現方式,具體緣由以下
1.RequireJS社區和文檔的支持比較完善
2,SeaJS項目中止維護
3.RequireJS在後續的版本中含括了SeaJS的功能
在實際的應用之中,通常模塊化是用來解決如下的幾種狀況的:
1. 解決文件與文件之間相互的依賴關係所產生的問題,方便後期代碼的升級維護。
2. 解決過渡加載不須要的函數代碼
3. 函數直接不會泄漏到全局
具體的用法不過多的解釋不懂點這裏:http://www.zhangxinxu.com/sp/seajs/docs/zh-cn/module-definition.html#define
寫這篇文章的時候已是2018年了,這些東西雖然能夠用,可是未免有些過期。
該文章主要是講關於閉包和模塊化在項目中要怎樣的合理使用,目前模塊化最好的解決方案我認爲是ES6的module。
可是考慮到團隊中可能水平良莠不齊,致使ES6推進的難度。因此建議首選ES6,次選RequireJS。
關於ES6的講解介紹會在以後的文章說起,若是以爲文章對你有幫助請點個贊。