成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

anonymoussf / 3264人閱讀

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

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

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

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

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

// 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)致了一不小心就會(huì)有變量沖突的問(wèn)題,就好比上面這個(gè)例子中的writeHello。

于是在2002年左右,有人提出了命名空間模式的思路,用于解決遍地的全局變量,將需要定義的部分歸屬到一個(gè)對(duì)象的屬性上,簡(jiǎn)單修改上面的例子,就能實(shí)現(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");
}

不過(guò)這種方式,毫無(wú)隱私可言,本質(zhì)上就是全局對(duì)象,誰(shuí)都可以來(lái)訪問(wèn)并且操作,一點(diǎn)都不安全。

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

// 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可以形成一個(gè)獨(dú)立的作用域,其中聲明的變量,僅在該作用域下,從而達(dá)到實(shí)現(xiàn)私有變量的目的,就如上面例子中的helloInLang,在該IIFE外是不能直接訪問(wèn)和操作的,可以通過(guò)暴露一些方法來(lái)訪問(wèn)和操作,比如說(shuō)上面例子里面的getHellowriteHello2個(gè)方法,這就是所謂的Closures。

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

// 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個(gè)好處:

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

壓縮空間:通過(guò)參數(shù)傳遞全局對(duì)象,壓縮時(shí)可以將這些全局對(duì)象匿名為一個(gè)更加精簡(jiǎn)的變量名;

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

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

沒(méi)有管理者的時(shí)候,在實(shí)際項(xiàng)目中,得手動(dòng)管理第三方的庫(kù)和項(xiàng)目封裝的模塊,就像下面這樣把所有需要的JS文件一個(gè)個(gè)按照依賴的順序加載進(jìn)來(lái):











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

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

閱讀需要支付1元查看
<