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