成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript模塊化開發(fā)的演進(jìn)歷程

anonymoussf / 3204人閱讀

摘要:參考精讀模塊化發(fā)展模塊化七日談前端模塊化開發(fā)那點歷史本文先發(fā)布于我的個人博客模塊化開發(fā)的演進(jìn)歷程,后續(xù)如有更新,可以查看原文。

Brendan Eich用了10天就創(chuàng)造了JavaScript,因為當(dāng)時的需求定位,導(dǎo)致了在設(shè)計之初,在語言層就不包含很多高級語言的特性,其中就包括模塊這個特性,但是經(jīng)過了這么多年的發(fā)展,如今對JavaScript的需求已經(jīng)遠(yuǎn)遠(yuǎn)超出了Brendan Eich的預(yù)期,其中模塊化開發(fā)更是其中最大的需求之一。

尤其是2009年Node.js出現(xiàn)以后,CommonJS規(guī)范的落地極大的推動了整個社區(qū)的模塊化開發(fā)氛圍,并且隨之出現(xiàn)了AMD、CMD、UMD等等一系列可以在瀏覽器等終端實現(xiàn)的異步加載的模塊化方案。

此前,雖然自己也一直在推進(jìn)模塊化開發(fā),但是沒有深入了解過模塊化演進(jìn)的歷史,直到最近看到了一篇文章《精讀JS模塊化發(fā)展》,文章總結(jié)了History of JavaScript這個開源項目中關(guān)于JavaScript模塊化演進(jìn)的部分,細(xì)讀幾次之后,對于一些以前模棱兩可的東西,頓時清晰了不少,下面就以時間線總結(jié)一下自己的理解:

1999年的時候,絕大部分工程師做JS開發(fā)的時候就直接將變量定義在全局,做的好一些的或許會做一些文件目錄規(guī)劃,將資源歸類整理,這種方式被稱為直接定義依賴,舉個例子:

// greeting.js
var helloInLang = {
  en: "Hello world!",
  es: "?Hola mundo!",
  ru: "Привет мир!"
};
function writeHello(lang) {
  document.write(helloInLang[lang]);
}

// third_party_script.js
function writeHello() {
  document.write("The script is broken");
}

// index.html



  
  Basic example
  
  



但是,即使有規(guī)范的目錄結(jié)構(gòu),也不能避免由此而產(chǎn)生的大量全局變量,這就導(dǎo)致了一不小心就會有變量沖突的問題,就好比上面這個例子中的writeHello。

于是在2002年左右,有人提出了命名空間模式的思路,用于解決遍地的全局變量,將需要定義的部分歸屬到一個對象的屬性上,簡單修改上面的例子,就能實現(xiàn)這種模式:

// greeting.js
var app = {};
app.helloInLang = {
  en: "Hello world!",
  es: "?Hola mundo!",
  ru: "Привет мир!"
};
app.writeHello = function (lang) {
  document.write(helloInLang[lang]);
}

// third_party_script.js
function writeHello() {
  document.write("The script is broken");
}

不過這種方式,毫無隱私可言,本質(zhì)上就是全局對象,誰都可以來訪問并且操作,一點都不安全。

所以在2003年左右就有人提出利用IIFE結(jié)合Closures特性,以此解決私有變量的問題,這種模式被稱為閉包模塊化模式

// greeting.js
var greeting = (function() {
  var module = {};
  var helloInLang = {
    en: "Hello world!",
    es: "?Hola mundo!",
    ru: "Привет мир!",
  };

  module.getHello = function(lang) {
    return helloInLang[lang];
  };

  module.writeHello = function(lang) {
    document.write(module.getHello(lang));
  };

  return module;
})();

IIFE可以形成一個獨立的作用域,其中聲明的變量,僅在該作用域下,從而達(dá)到實現(xiàn)私有變量的目的,就如上面例子中的helloInLang,在該IIFE外是不能直接訪問和操作的,可以通過暴露一些方法來訪問和操作,比如說上面例子里面的getHellowriteHello2個方法,這就是所謂的Closures。

同時,不同模塊之間的引用也可以通過參數(shù)的形式來傳遞:

// x.js
// @require greeting.js
var x = (function(greeting) {
  var module = {};

  module.writeHello = function(lang) {
    document.write(greeting.getHello(lang));
  };

  return module;
})(greeting);

此外使用IIFE,還有2個好處:

提高性能:通過IIFE的參數(shù)傳遞常用全局對象window、document,在作用域內(nèi)引用這些全局對象。JavaScript解釋器首先在作用域內(nèi)查找屬性,然后一直沿著鏈向上查找,直到全局范圍,因此將全局對象放在IIFE作用域內(nèi)可以提升js解釋器的查找速度和性能;

壓縮空間:通過參數(shù)傳遞全局對象,壓縮時可以將這些全局對象匿名為一個更加精簡的變量名;

在那個年代,除了這種解決思路以外,還有通過其它語言的協(xié)助來完成模塊化的解決思路,比如說模版依賴定義、注釋依賴定義、外部依賴定義等等,不過不常見,所以就不細(xì)說了,究其本源,它們想最終實現(xiàn)的方式都差不多。

不過,這些方案,雖然解決了依賴關(guān)系的問題,但是沒有解決如何管理這些模塊,或者說在使用時清晰描述出依賴關(guān)系,這點還是沒有被解決,可以說是少了一個管理者。

沒有管理者的時候,在實際項目中,得手動管理第三方的庫和項目封裝的模塊,就像下面這樣把所有需要的JS文件一個個按照依賴的順序加載進(jìn)來:












如果頁面中使用的模塊數(shù)量越來越多,恐怕再有經(jīng)驗的工程師也很難維護(hù)好它們之間的依賴關(guān)系了。

于是如LABjs之類的加載工具就橫空出世了,通過使用它的API,動態(tài)創(chuàng)建

閱讀需要支付1元查看
<