實現javascript下的模組組織

來源:互聯網
上載者:User

標籤:java

java有類檔案、Python有import關鍵詞、Ruby有require關鍵詞、C#有using關鍵詞、PHP有include和require、CSS有@import關鍵詞,但是對ES5版本的javascript來說,javascript通過script標籤引入代碼的方式顯得雜亂無章,語言自身毫無組織和約束能力,人們不得不用命令空間等方式人為地約束代碼,以求達到安全和易用的目的。本文將詳細介紹javascript中的模組組織

 

反模式

  反模式(Anti-Pattern)指沒有使用任何模組系統

  簡單地,把不同的函數(以及選項組的變數)放在一起,就算是一個模組

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

  function m1(){    //...  }  function m2(){    //...  }

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

  上面的函數m1()和m2(),組成一個模組。使用的時候,直接調用就行了。

  這種做法的缺點很明顯:"汙染"了全域變數,無法保證不與其他模組發生變數名衝突,而且模組成員之間看不出直接關係

 

字面量

  為瞭解決上面的缺點,可以把模組寫成一個字面量,所有的模組成員都放到這個對象裡面

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

  var module1 = new Object({    _count : 0,    m1 : function (){      //...    },    m2 : function (){      //...    }  });

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

  上面的函數m1()和m2(),都封裝在module1對象裡。使用的時候,就是調用這個對象的屬性

module1.m1();

  但這種寫法會暴露所有模組成員,內部狀態可被外部改寫。比如,外部代碼可以直接改變內部計數器的值

module1._count = 5;

 

IIFE

  使用"立即執行函數"(Immediately-Invoked Function Expression,IIFE)可以達到不暴露私人成員的目的

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

  var module1 = (function(){    var _count = 0;    var m1 = function(){      //...    };    var m2 = function(){      //...    };    return {      m1 : m1,      m2 : m2    };  })();

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

  使用上面的寫法,外部代碼無法讀取內部的_count變數

console.info(module1._count); //undefined

 

IIFE傳參

  如果一個模組需要繼承另一個模組,則需要IIFE傳參

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

  var module1 = ( function (mod){    mod.m3 = function () {      //...    };    return mod;  })(window.module1 || {});

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

 

命名空間

  如果採用IIFE的方法,隨著模組的增多,仍然汙染了全域環境。

  而命名空間(Namespace)可以通過只暴露類似於一個‘namespace‘的全域變數,來實現所有模組的聲明,進而解決全域環境的汙染問題

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

//math.jsnamespace(‘math‘, [], function(){  function add(a, b) { return a + b; }  function sub(a, b) { return a - b; }  return {    add: add,    sub: sub  }})//calculator.jsnamespace(‘calculator‘, [‘math‘], function(m){  var action = ‘add‘;  function compute(a,b) {    return m[action](a, b);  }  return {    compute: compute  }})

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

var namespace = (function(){    //緩衝所有模組    var cache = {};    function createModule(name/*模組名*/,deps/*依賴列表*/,definition/*定義*/){        //如果只有模組名,則直接輸出        if(arguments.length === 1){            return cache[name];        }        //取得所有模組的依賴        deps = deps.map(function(depName){            return namespace(depName);         })        //初始化模組並返回        cache[name] = definition.apply(null,deps);        return cache[name];    }    return createModule;})()

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;float:left;border:none;" />

 

最後

  雖然,使用命名空間可以解決全域環境汙染的問題,但是卻無法解決模組依賴管理的問題

  如所示,module2依賴於module1和module3,則代碼如下

650) this.width=650;" src="http://images2015.cnblogs.com/blog/740839/201705/740839-20170512163838676-1698856628.png" style="border:none;margin-top:20px;margin-bottom:20px;" />

<script src="module1.js"></script><script src="module3.js"></script><script src="module2.js"></script>

  但,如果模組組織如下所示

650) this.width=650;" src="http://images2015.cnblogs.com/blog/740839/201705/740839-20170512164300832-421694311.png" style="border:none;margin-top:20px;margin-bottom:20px;" />

  甚至,如下所示

650) this.width=650;" src="http://images2015.cnblogs.com/blog/740839/201705/740839-20170512164314582-1695611926.png" style="border:none;margin-top:20px;margin-bottom:20px;" />

  這時,手動地處理模組之間的依賴關係就不現實了,需要使用AMD、CMD、ES6 MODULE等來處理


實現javascript下的模組組織

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.