造輪子和用輪子:快速入門JavaScript模塊化

zihao_123 8年前發布 | 15K 次閱讀 JavaScript開發 JavaScript

來自: https://segmentfault.com/a/1190000004619857

前言

都說“不重復造輪子”,就像iPhone——它除了打電話還可以播放音樂——但是工程師不用從零開始做一個音樂播放功能,也許只要在iPhone的系統中整合一個ipod。

前端開發亦是如此,最理想化的開發狀態就是,工程師只寫核心業務代碼,其他通用的功能和組件都可以無縫加載別人寫好的代碼,就像很多那樣。

可是實際情況是,有個糟糕的 iPhone 工程師,他搞混了 iPhone 和 ipod 的系統,甚至把 iPhone 的 Home 鍵和 iPod 的音量鍵焊在同一個。

還有一些糟糕 JavaScript 開發者,一不小心聲明了全局變量,混亂了“命名空間”,都讓協作開發變得不那么友好,抑或他開發了一個通用模塊,用戶們卻發現載入了他的代碼之后,用戶自己的代碼被他搞得一團糟。

原始人寫法

比如下面這段代碼:

var mylove = "coding";

function getLove() { return mylove; }

function sayLove(thing) { console.log(thing); }

console.log(getLove());//>>> coding sayLove('girl');//>>> girl</pre>

在 window 對象下聲明了一個變量 mylove ,然后使用 getLove() 函數去獲取這個變量,使用 setLove() 修改這個變量。

恩,功能是實現了。只是這樣做之后,說不定什么時候你由于粗心又在某個地方聲明了一次 mylove ,而你的粗心同事也不知道會在什么地方寫了一個同名函數——也許有3個參數的 setLove() 函數。

</div>

對象封裝寫法

怎么辦呢?你獲取想到了,把這些變量和函數都寫在一個對象里:

var loveThing = {
  mylove : "coding",
  getLove :function() {
    return this.mylove;
  },
  sayLove : function(thing) {
    console.log(thing);
  }
}

console.log(loveThing.getLove());//>>> coding loveThing.sayLove('girl');//>>> girl</pre>

這種寫法已經有點模塊的樣子了,一下就能看出這幾個函數和變量之間的聯系。缺點在于所有變量都必須聲明為公有,所以都要加this指示作用域以引用這些變量。更危險的是,在對象之外也能輕松更改里面的參數:

loveThing.mylove = "sleeping";
console.log(loveThing.getLove());//>>> sleeping

立即執行函數

我向來不憚以最壞的惡意揣測程序員,你永遠想不到你的 partner 會不會真的在其他地方修改了你的參數,也不知道自己是否會在不經意間修改了他的。我們必須在他下手之前——讓自己的模塊先執行掉,不給對方可趁之機。此時使用一種叫做 立即執行函數 的辦法,可以避免暴露私有成員。

var loveThing = (function(){
  var my = {};
  var love = "coding";
  my.getLove = function() {
    return love;
  }
  my.sayLove = function(thing) {
    console.log(thing);
  }
  return my;
})();

console.log(loveThing.getLove());//>>> coding loveThing.sayLove('reading');//>>> reading</pre>

我們試著獲取里面的變量:

console.log(loveThing.love);//>>> undefined

果然,外部根本看不見里面的零件,只能使用提供的接口。這樣才能保證私有變量的安全。

放大模式

當然,一個項目要用到模塊化的時候,說明這個項目足夠大足夠復雜,一個模塊可能需要繼承另一個模塊,或者擴充模塊,這時候需要使用 放大模式

var loveThing = (function (o){
  o.sayOK = function () {
    console.log('OK');
  };
  return o;
})(loveThing);

loveThing.sayOK();//>>> OK!</pre>

寬放大模式

可是,瀏覽器是一個不按常理出牌的環境,你永遠不知道自己引用的模塊是否已經加載。萬一我之前的 loveThing 沒有被加載,上面這段代碼就會報錯了(找不到對象)。解決方法就是所謂 寬放大模式

var loveThing = (function (o){
  o.sayOK = function () {};
  return o;
})(loveThing || {});

與之前唯一的不同就是參數可以為空對象。

至此,最基本的JavaScript模塊化寫法你已經學會了,相信你也體會到自己原來的寫法有什么不足。

受篇幅限制,本篇入門到此結束,我會在下一篇討論流行的模塊化規范。

</div>

 本文由用戶 zihao_123 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!