摘要:常見模塊化方案是由社區(qū)提出的模塊化方案中的一種,遵循了這套方案。是模塊化規(guī)范中的一種,遵循了這套規(guī)范。中的模塊化能力由兩個命令構(gòu)成和,命令用于規(guī)定模塊的對外接口,命令用于輸入其他模塊提供的功能。
為什么需要模塊化
在ES6出現(xiàn)之前,JS語言本身并沒有提供模塊化能力,這為開發(fā)帶來了一些問題,其中最重要的兩個問題應(yīng)當(dāng)是全局污染和依賴管理混亂。
// file a.js var name = "aaa"; var sayName = function() { console.log(name); };
上面的代碼中,我們兩次調(diào)用a.js所提供的sayName函數(shù)輸出了不同結(jié)果,很明顯這是因為兩個文件都對變量name進(jìn)行了賦值,因此相互之間造成了影響。當(dāng)然我們可以在編寫代碼時注意不要定義已存在的變量名,但是當(dāng)一個頁面引用了10幾個幾百行的文件時,記住所有已經(jīng)定義過的變量顯然不太現(xiàn)實。
// file a.js var name = getName(); var sayName = function() { console.log(name) };
// file b.js var getName = function() { return "timo"; };
// Uncaught ReferenceError: getName is not defined
上面的代碼說明,多個文件有依賴關(guān)系時,我們需要確保其引入的順序,從而保證運行某個文件時,其依賴已經(jīng)提前加載,可以想象,面對越大型的項目,我們需要處理的依賴關(guān)系也就越多,這既麻煩又容易出錯。
而為了解決這些,社區(qū)中出現(xiàn)了許多為JS語言提供模塊化能力的規(guī)范,借助這些規(guī)范,能讓我們的開發(fā)更加方便安全。
常見模塊化方案 CommonJSCommonJS是由社區(qū)提出的模塊化方案中的一種,Node.js遵循了這套方案。
基本寫法// file a.js var obj = { sayHi: function() { console.log("I am timo"); }; }; module.exports obj;
// file b.js var Obj = require("xxx/xxx/a.js"); Obj.sayHi(); // "I am timo"
上面的代碼中,文件a.js是模塊的提供方,文件b.js是模塊調(diào)用方。
規(guī)范每個文件都是一個模塊;
在模塊內(nèi)提供module對象,表示當(dāng)前模塊;
模塊使用exports對外暴露自身的函數(shù)/對象/變量等;
模塊內(nèi)通過require()方法導(dǎo)入其他模塊;
CommonJS的規(guī)范,簡單來說就是上面4條,可以對照基本寫法中的例子理解一下,在實際實現(xiàn)中,Node.js雖然遵循CommonJS規(guī)范,但是仍然對其進(jìn)行了一些調(diào)整。
AMDAMD是模塊化規(guī)范中的一種,RequireJS遵循了這套規(guī)范。
基本用法// file a.js define("module", ["m", "./xxx/n.js"], function() { // code... })
上面的代碼中,文件a.js向外導(dǎo)出了模塊;
規(guī)范AMD中,暴露模塊使用define函數(shù)
define(moduleName, [], callback);
如上面代碼,define函數(shù)共有三個參數(shù)
moduleName該參數(shù)可以省略,表示該模塊的名字,一般作用不大
["name1", "name2"],第二個參數(shù)是一個數(shù)組,表示當(dāng)前模塊依賴的其他模塊,如果沒有依賴模塊,該參數(shù)可以省略
callback,第三個參數(shù)是必傳參數(shù),是一個回調(diào)函數(shù),內(nèi)部是當(dāng)前模塊的相關(guān)代碼
其他ADM的特點是依賴前置,這是ADM規(guī)范與接下來要介紹的CMD規(guī)范最大的不同,依賴前置是指:在運行當(dāng)前加載模塊回調(diào)前,會首先將所有依賴包加載完畢,也是就是define函數(shù)的第二個參數(shù)中指定的依賴包。
CDM 基本寫法define(function(require, exports, module) { var a = require("./a") a.doSomething(); // code... var b = require("./b") // code... })
上面代碼是CMD規(guī)范導(dǎo)出模塊的基本寫法;
規(guī)范從寫法可以看出,CMD的寫法和AMD非常像,其主要區(qū)別是對于依賴加載時機的不同,上面已經(jīng)說過,AMD是依賴前置,而CMD規(guī)范推崇就近原則,簡單說就是在模塊運行前并不加載依賴,模塊運行過程中,當(dāng)需要某個依賴時,再去進(jìn)行加載。
UMDCommonJS、AMD、CMD并行的狀態(tài)下,就需要一種方案能夠兼容他們,這樣我們在開發(fā)時,就不需要再去考慮依賴模塊所遵循的規(guī)范了,而UMD的出現(xiàn)就是為了解決這個問題。
基本寫法(function (root, factory) { if (typeof define === "function" && define.amd) { //AMD define(["jquery"], factory); } else if (typeof exports === "object") { //Node, CommonJS之類的 module.exports = factory(require("jquery")); } else { //瀏覽器全局變量(root 即 window) root.returnExports = factory(root.jQuery); } }(this, function ($) { //方法 function myFunc(){}; //暴露公共方法 return myFunc; }));
上面的代碼是UMD的基本寫法,從代碼就可以看出,其能夠同時支持CommonJS規(guī)范和AMD規(guī)范。
ES6 module上面分別介紹了CommonJS、AMD、CMD和UMD,他們都是社區(qū)對于JS實現(xiàn)模塊化的貢獻(xiàn),這個規(guī)范其產(chǎn)生的根本原因,都是JS語言自身沒有模塊化能力,而目前,在JS最新的語言規(guī)范ES6中,已經(jīng)為JS增加了模塊化能力,而JS自身的模塊化方案,完全能夠替代目前社區(qū)提出的各類規(guī)范,且能夠做到瀏覽器端和Node端通用。
ES6中的模塊化能力由兩個命令構(gòu)成:export和import,export命令用于規(guī)定模塊的對外接口,import命令用于輸入其他模塊提供的功能。
export命令ES6中一個文件就是一個模塊,模塊內(nèi)部的變量/函數(shù)等外部是無法訪問的,如果希望將內(nèi)部的函數(shù)/變量等對外暴露,供其他模塊進(jìn)行使用,就需要通過export命令進(jìn)行導(dǎo)出
// file a.js export let a = 1; export let b = 2; export let c = 3;
// file b.js let a = 1; let b = 2; let c = 3; export {a, b, c}
// file c.js export let add = (a, b) => { return a + b; };
上面三個文件的代碼,都是通過export命令導(dǎo)出模塊內(nèi)容的示例,其中a.js文件和b.js文件都是導(dǎo)出模塊中的變量,作用完全一致但寫法不同,一般我們更推薦b.js文件中的寫法,原因是這種寫法能夠在文件最底部清楚地知道當(dāng)前模塊都導(dǎo)出了哪些變量。
import命令模塊通過export命令導(dǎo)出變量/函數(shù)等,是為了讓其他模塊能夠?qū)肴ナ褂?,在ES6中,文件導(dǎo)入其他模塊是通過import命令進(jìn)行的
// file d.js import {a, b, c} from "./a.js";
上面的代碼中,我們引入了a.js文件中的變量a、b、c,import在引入其他模塊內(nèi)的函數(shù)/變量時,必須與原模塊所暴露出來的函數(shù)名/變量名一一對應(yīng)。
同時,import命令引入的值是只讀的,如果嘗試對其進(jìn)行修改,則會報錯
import {a} d from "./a.js"; a = 2; // Syntax Error : "a" is read-only;export default命令
從上面import的介紹可以看到,當(dāng)需要引入其他模塊時,需要知道此模塊暴露出的變量名/函數(shù)名才可以,這顯然有些麻煩,因此ES6還提供了一個import default命令
// file a.js let add = (a, b) => { return a+b }; export default add;
// file b.js import Add from "./a.js"; Add(1, 2); // 3
上面的代碼中,a.js通過export default命令導(dǎo)出了add函數(shù),在b.js文件中引入時,可以隨意指定其名稱
export default命令是默認(rèn)導(dǎo)出的意思,既然是默認(rèn)導(dǎo)出,顯然只能有一個,因此每個模塊只能執(zhí)行一次export default命令,其本質(zhì)是導(dǎo)出了一個名為default的變量或函數(shù)。
總結(jié)最后再來總結(jié)一下, 首先在之前的JS語言中沒有模塊化能力,而隨著網(wǎng)站功能的復(fù)雜,開發(fā)越來越不方便,因此社區(qū)中出現(xiàn)了一批為JS提供模塊化能力的方案,其中比較主流的就是我們介紹過的CommonJS、AMD、CMD和UMD等,而之后發(fā)布的ES6語言標(biāo)準(zhǔn),從JS語言自身提供了模塊化能力,因此,隨著ES6的逐步普及,ES6 module應(yīng)該會逐步取代目前的各類社區(qū)規(guī)范,但不可否認(rèn),在沒有ES6的日子里,這些社區(qū)規(guī)范給前端人員提供了巨大的方便,并推動了JS的發(fā)展。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/98701.html
摘要:即盡早地執(zhí)行依賴模塊。阮一峰輸出值的引用模塊是動態(tài)關(guān)聯(lián)模塊中的值,輸出的是值得引用。的加載實現(xiàn)阮一峰運行時加載靜態(tài)編譯模塊是運行時加載,模塊是編譯時輸出接口。 模塊化開發(fā) 優(yōu)點 模塊化開發(fā)中,通常一個文件就是一個模塊,有自己的作用域,只向外暴露特定的變量和函數(shù),并且可以按需加載。 依賴自動加載,按需加載。 提高代碼復(fù)用率,方便進(jìn)行代碼的管理,使得代碼管理更加清晰、規(guī)范。 減少了命名沖...
摘要:若不存在則模塊標(biāo)識應(yīng)該默認(rèn)定義為在加載器中被請求腳本的標(biāo)識。這也是目前很多插件頭部的寫法,就是用來兼容各種不同模塊化的寫法。語句輸出的值是動態(tài)綁定的,綁定其所在的模塊。 前言 歷史上,js沒有模塊化的概念,不能把一個大工程分解成很多小模塊。這對于多人開發(fā)大型,復(fù)雜的項目形成了巨大的障礙,明顯降低了開發(fā)效率,java,Python有import,甚至連css都有@import,但是令人費...
摘要:而前端要使用模塊化的原因或者要解決的問題就是解決命名沖突管理依賴提高代碼的可復(fù)用性相關(guān)模塊化規(guī)范常見的規(guī)范有規(guī)范規(guī)范是在推廣過程中對模塊定義的規(guī)范化產(chǎn)出,主要用于瀏覽器端。目前的各類全局變量都可以模塊化。 開發(fā)中明顯可以感覺到加載一個HTML需要依賴很多的JS文件依賴,比如到一定階段的HTML頁面,尾部就是這樣的: 隨著所需功能越來越多,我們就需引入更多的JS依...
摘要:一模塊化命名空間二命名空間庫名類別名方法名三規(guī)范一個文件為一個模塊,通過暴露快接口,通過引入模塊,同步執(zhí)行文檔示例四規(guī)范使用定義模塊使用加載模塊依賴前置,提前執(zhí)行規(guī)范文檔示例模塊名字模塊輸出模塊輸出等于在最前面聲明并初始化了要用到的模塊即使 一、js模塊化 命名空間 commonJS AMD/CMD/UMD ES6 module 二、命名空間 庫名.類別名.方法名 var NameSp...
摘要:一模塊化命名空間二命名空間庫名類別名方法名三規(guī)范一個文件為一個模塊,通過暴露快接口,通過引入模塊,同步執(zhí)行文檔示例四規(guī)范使用定義模塊使用加載模塊依賴前置,提前執(zhí)行規(guī)范文檔示例模塊名字模塊輸出模塊輸出等于在最前面聲明并初始化了要用到的模塊即使 一、js模塊化 命名空間 commonJS AMD/CMD/UMD ES6 module 二、命名空間 庫名.類別名.方法名 var NameSp...
閱讀 2037·2021-11-15 11:38
閱讀 2072·2019-08-30 15:55
閱讀 2208·2019-08-30 15:52
閱讀 3191·2019-08-30 14:01
閱讀 2714·2019-08-30 12:47
閱讀 1194·2019-08-29 13:17
閱讀 1089·2019-08-26 13:55
閱讀 2659·2019-08-26 13:46