前端開發模塊化規範

1、CommonJS

Node.js是commonJS規範的主要實踐者,它有四個重要的環境變量爲模塊化的實現提供支持:module、exports、require、global。實際使用時,用module.exports定義當前模塊對外輸出的接口(不推薦直接用exports),用require加載模塊。
// 定義模塊math.js
var basicNum = 0;
function add(a, b) {
return a + b;
}
module.exports = { //在這裏寫上須要向外暴露的函數、變量
add: add,
basicNum: basicNum
}
// 引用自定義的模塊時,參數包含路徑,可省略.js
var math = require(‘./math’);
math.add(2, 5);
// 引用核心模塊時,不須要帶路徑
var http = require(‘http’);
http.createService(…).listen(3000);
commonJS用同步的方式加載模塊。在服務端,模塊文件都存在本地磁盤,讀取很是快,因此這樣作不會有問題。可是在瀏覽器端,限於網絡緣由,更合理的方案是使用異步加載。
 

2、AMD和require.js

AMD規範採用異步方式加載模塊,模塊的加載不影響它後面語句的運行。全部依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成以後,這個回調函數纔會運行。這裏介紹用require.js實現AMD規範的模塊化:用require.config()指定引用路徑等,用define()定義模塊,用require()加載模塊。
首先咱們須要引入require.js文件和一個入口文件main.js。main.js中配置require.config()並規定項目中用到的基礎模塊。
/** 網頁中引入require.js及main.js **/
/** main.js 入口文件/主模塊 **/
// 首先用config()指定各模塊路徑和引用名
require.config({
baseUrl: 「js/lib」,
paths: {
「jquery」: 「jquery.min」, //實際路徑爲js/lib/jquery.min.js
「underscore」: 「underscore.min」,
}
});
// 執行基本操做
require([「jquery」,」underscore」],function($,_){
// some code here
});
引用模塊的時候,咱們將模塊名放在[]中做爲reqiure()的第一參數;若是咱們定義的模塊自己也依賴其餘模塊,那就須要將它們放在[]中做爲define()的第一參數。
// 定義math.js模塊
define(function () {
var basicNum = 0;
var add = function (x, y) {
return x + y;
};
return {
add: add,
basicNum :basicNum
};
});
// 定義一個依賴underscore.js的模塊
define([‘underscore’],function(_){
var classify = function(list){
_.countBy(list,function(num){
return num > 30 ? ‘old’ : ‘young’;
})
};
return {
classify :classify
};
})
// 引用模塊,將模塊放在[]內
require([‘jquery’, ‘math’],function($, math){
var sum = math.add(10,20);
$(「#sum」).html(sum);
});

  

3、CMD和sea.js

require.js在申明依賴的模塊時會在第一之間加載並執行模塊內的代碼:
define([「a」, 「b」, 「c」, 「d」, 「e」, 「f」], function(a, b, c, d, e, f) {
// 等於在最前面聲明並初始化了要用到的全部模塊
if (false) {
// 即使沒用到某個模塊 b,但 b 仍是提早執行了
b.foo()
}
});
CMD是另外一種js模塊化方案,它與AMD很相似,不一樣點在於:AMD 推崇依賴前置、提早執行,CMD推崇依賴就近、延遲執行。此規範實際上是在sea.js推廣過程當中產生的。
/** AMD寫法 **/
define([「a」, 「b」, 「c」, 「d」, 「e」, 「f」], function(a, b, c, d, e, f) {
// 等於在最前面聲明並初始化了要用到的全部模塊
a.doSomething();
if (false) {
// 即使沒用到某個模塊 b,但 b 仍是提早執行了
b.doSomething()
}
});
/** CMD寫法 **/
define(function(require, exports, module) {
var a = require(‘./a’); //在須要時申明
a.doSomething();
if (false) {
var b = require(‘./b’);
b.doSomething();
}
});
/** sea.js **/
// 定義模塊 math.js
define(function(require, exports, module) {
var $ = require(‘jquery.js’);
var add = function(a,b){
return a+b;
}
exports.add = add;
});
// 加載模塊
seajs.use([‘math.js’], function(math){
var sum = math.add(1+2);
});

  

 
 


4、ES6 Module

ES6 在語言標準的層面上,實現了模塊功能,並且實現得至關簡單,旨在成爲瀏覽器和服務器通用的模塊解決方案。其模塊功能主要由兩個命令構成:export和import。export命令用於規定模塊的對外接口,import命令用於輸入其餘模塊提供的功能。
/** 定義模塊 math.js **/
var basicNum = 0;
var add = function (a, b) {
return a + b;
};
export { basicNum, add };
/** 引用模塊 **/
import { basicNum, add } from ‘./math’;
function test(ele) {
ele.textContent = add(99 + basicNum);
}

  

如上例所示,使用import命令的時候,用戶須要知道所要加載的變量名或函數名。其實ES6還提供了export default命令,爲模塊指定默認輸出,對應的import語句不須要使用大括號。這也更趨近於ADM的引用寫法。
/** export default **/
//定義輸出
export default { basicNum, add };
//引入
import math from ‘./math’;
function test(ele) {
ele.textContent = math.add(99 + math.basicNum);
}

  

ES6的模塊不是對象,import命令會被 JavaScript 引擎靜態分析,在編譯時就引入模塊代碼,而不是在代碼運行時加載,因此沒法實現條件加載。也正由於這個,使得靜態分析成爲可能。
 


5、 ES6 模塊與 CommonJS 模塊的差別

1.CommonJs模塊輸出的是一個值的拷貝,ES6模塊輸出的是值的引用。
 
CommonJS模塊輸出的是值的拷貝,也就是說,一旦輸出一個值,模塊內部的變化就 影響不到這個值。
 
ES6模塊的運行機制與CommonJS不同。JS引擎對腳本靜態 分析的時候,遇到的模塊家在命令import,就會
 
生成一個只讀引用。等到腳本真正執行時,再根據這個只讀引用,到被加載的那個模塊裏面去取值。換句話說,ES6 的import有點像模塊裏面的變量綁定其所在的模塊。
 
2. CommonJS 模塊是運行時加 Unix 系統的「符號鏈接」,原始值變了,import加載的值也會跟着變。所以,ES6 模塊是動態引用,而且不會緩存值,載,ES6 模塊是編譯時輸出接口。
 
運行時加載: CommonJS 模塊就是對象;即在輸入時是先加載整個模塊,生成一個對象,而後再從這個對象上面讀取方法,這種加載稱爲「運行時加載」。
 
編譯時加載: ES6 模塊不是對象,而是經過 export 命令顯式指定輸出的代碼,import時採用靜態命令的形式。即在import時能夠指定加載某個輸出值,而不是加載整個模塊,這種加載稱爲「編譯時加載」。CommonJS 加載的是一個對象(即module.exports屬性),該對象只有在腳本運行完纔會生成。而 ES6 模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。
相關文章
相關標籤/搜索