什么是模塊化?以及它的好處。


.什么是模塊化?

簡單地說,模塊化就是有組織地把一個大文件拆成獨立並互相依賴的多個小模塊。
模塊內部有許多私有屬性,只向外暴露一部分公開的接口(如可以修改私有屬性的方法等)

2.為什么要模塊化?

ES6之前,JavaScript語言一直沒有模塊(module)體系,無法把大文件有組織地划分成小塊,並管理之間地依賴。但是模塊化的思想一直存在。因為用Javascript寫的代碼越來越龐大,而網頁也越來越像桌面APP。如此龐雜的代碼,如果不進行模塊化,就可能引發命名沖突,造成不易復用、維護性高。

 

模塊化的好處

  • 避免命名沖突(減少命名空間污染)
  • 更好的分離, 按需加載
  • 更高復用性
  • 高可維護性
3.模塊划分

一般,為了清晰明了,一個文件對應一個模塊。

二、模塊化規范

1. CommonJS

Node.js遵循的規范

const { PI } = Math; module.exports.getArea = (r) => PI * r * 2; // 向外暴露(計算圓形的面積的)getArea方法 

注意,這里的module可省略(不推薦),寫成:

const { PI } = Math exports.getArea = (r) => PI * r * 2 // 向外暴露(計算圓形的面積的)getArea方法(省略了module) 

特點:

1.代碼運行在模塊作用域,不會污染全局
2.加載模塊順序按照詞法解析的順序加載
3.加載模塊是同步的
4.單例加載:也就是加載的模塊會緩存起來,再次使用時,會直接用運行結果,不會再加載(除非手動清除)
5.加載模塊得到的是結果的拷貝

2. AMD

RequireJS遵循的規范
AMD用define()定義模塊,用require()加載模塊。

// 定義一個新的模塊,這個新的模塊可能用到a模塊和b模塊 // define第一個參數是 依賴模塊的數組,對應callback里的參數 define(["a", "b"], function(a, b) { // 1. 在最前面加載了a、b // 2. 使用模塊a const a = require('./a') // a在最前面已經加載好了 // 3.處理其他代碼 if (false) { // 這里實際上是不可達代碼(永遠不會被執行) // 所以b實際不需要加載。然而因為AMD是依賴前置、提前執行的, // 所以b還是會在最前面被提前加載的 console.log(b.getArea(1)) // 6.283185307179586 } // 向外暴露接口(寫法1) const getArea = (r) => PI * r * 2 return { getArea } // 向外暴露接口(寫法2) const getArea2 = (r) => PI * r * 2 exports.getArea2 = getArea2 }); 

特點:

1.加載模塊推崇依賴前置、提前執行
2.加載模塊是異步的

3. CMD

sea.js遵循的規范
CMD也是用define()定義模塊,用require()加載模塊,但思想不同、寫法也不同。
CMD規范是在sea.js推廣的過程中產生的,寫法如下:

// 定義一個新的模塊,這個新的模塊可能用到a模塊和b模塊 // define接收一個callback參數,對應 define(function(require, exports, module) { // 最前面不提前加載模塊 // 1. 使用模塊a const a = require('./a') // 依賴就近、延遲執行,需要a,就去require a // 2.處理其他代碼 if(false) { // 這里實際上是不可達代碼(永遠不會被執行) // 所以b實際不需要加載。恰好CMD是依賴就近、延遲執行的, // 所以b的確是不會被加載的 const b = require('./b') // 處理其他代碼 } // 向外暴露接口(寫法1) const getArea = (r) => PI * r * 2 return { getArea } // 向外暴露接口(寫法2) const getArea2 = (r) => PI * r * 2 exports.getArea2 = getArea2 }) // 使用的地方: seajs.use(['a.js'], function(a){ // 依賴就近,需要a,就去require a console.log(a.getArea(1)) // 6.283185307179586 }) 

特點:

1.加載模塊推崇依賴就近、延遲執行
2.加載模塊也是異步的

4. ES6 模塊

ES6 模塊的設計思想是盡量的靜態化,使得編譯時就能確定模塊的依賴關系

// a.js const getArea = (r) => PI * r * 2 export { getArea } // 向外暴露一個對象,對象有一個(計算圓形的面積的)方法getArea // 使用的地方: import { getArea } = './a.js' // 注意這里拿到的是一個對象,對象里有getArea方法 console.log(getArea(1)) // 6.283185307179586 

ES6還提供了一個default,用來提供默認的export:

// a.js const getArea = (r) => PI * r * 2 export default getArea // 向外直接暴露一個(計算圓形的面積的)方法getArea // 用的地方: import getArea = './a.js' // 注意這里拿到的就是getArea方法 console.log(getArea(1)) // 6.283185307179586 

特點:

1.編譯時確定模塊的依賴關系
2.加載模塊存儲的是值的引用,所以全局只有一份
3.加載模塊也是異步的

三、總結

最開始,JavaScript沒有模塊。后來:

有CommoneJS規范,最典型的實踐就是Node.js,主要使用在服務器端,同步加載模塊;

有AMD,最典型的實踐就是RequireJS,依賴前置,主要使用在瀏覽器端,異步加載模塊。

有CMD,最典型的實踐就是sea.js,依賴就近,主要使用在瀏覽器端,異步加載模塊。

有ES6的Module,在語言層面定義了模塊,通過export和import,吸收了CommoneJS和AMD兩者的優點,兼容兩標准的規范




鏈接:https://www.jianshu.com/p/480496c3c671
來源:簡書


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM