簡析-commonJS&AMD&CMD

簡析-commonJS&AMD&CMD

大概說下三者區別:

歷史流水線:

CommonJS ---> AMD ---> CMDjavascript

共同點:

  1. 都是使用字符串命名方式,讓模塊做用域只存在於當前模塊做用域內,解決了命名空間的問題,且遵循一個模塊表明一個文件的理念,將一個js系統地「分割「成多個模塊,實現模塊化系統。前端

  2. AMD和CMD都是向着CommonJS致敬的,都有CommonJS的身影。java

不一樣點:

  1. CommonJS起初爲了解決,服務端的代碼,把代碼全都擠在一個文件內,從而致使文件複雜臃腫的,瀏覽器加載該JS文件,產生卡死;全局做用域污染等問題,而應運而生的模塊化開發理念。並且其加載模塊的方式屬於同步的,須要遵循「先加載,停頓,再執行「的順序來執行代碼,所以很受網速限制。node

  2. AMD規範,雖然延續了CommonJS的理念,模塊化開發,但不一樣的是,AMD遵循的是異步加載模塊的規範。其加載依賴模塊方式是屬於依賴前置,即先加載須要的依賴模塊,再執行回調函數,大大提升了效率。python

  3. CMD規範,是由國內前端大神,玉伯,編寫的一個js庫 --- sea.js,在推過過程,提出的一個基於CommonJS的新規範---CMD。該規範與AMD相似,寫法也相似。但不一樣的是,CMD遵循着依賴後置的理念。即AMD是一次性加載完該模塊所須要的全部模塊,再執行回調。而CMD是按需加載,即須要用到的時候,纔去加載對應模塊。git

  4. 雖然說AMD和CMD表明分別是requireJS和seaJS,但要清楚一點,前面2個是規範,後面2個是庫,只是模塊加載器。github


1. CommonJS

介紹 : CommonJS,期初名字是叫SeverJS,後改成CommonJS。其定義了服務器端模塊的規範,記住,只是規範,由Node推廣使用(適用於服務端)。api

CommonJS 經過定義一些常見應用程序的API的方式,爲模塊化開發 JS 提供了一個標準庫(後來逐漸造成了規範),用來兼容不一樣JS解釋器和宿主環境。數組

其目標是提供一個標準庫,這個庫類比於python,java...瀏覽器

主要做用是爲一些特定對象,定義一些API,提供module.exports來導出模塊,require來導入模塊。

表明:

NodeJS

背景:

因爲初期js的侷限性,項目累計起來,就會全部代碼寫進一個文件內,容易致使文件過大,加載過久,瀏覽器容易卡死,關鍵之前網速和如今千差萬別;

不只如此,還會致使做用域污染的問題(全局污染),造成命名空間。並且也不方便與其它項目的系統進行進行交互(這裏主要指基於瀏覽器的應用)。

所以,模塊化開發成了必然趨勢,因而便有了Common Js。

然而在2009年,一位美國佬建立了一個語言上基於js,規範遵循着時下流行且實用的CommonJS規範的Node JS,更是將CommonJS推向了高潮,得益於node Js的火熱。

主要API:

1. module.exports      ------      用於導出當前模塊。
2. require      ------      這個require和AMD的require不一樣。
複製代碼

優勢:

  1. 模塊化,遵循一個模塊一個文件的原則。

  2. 耦合低,不容易致使全局變量的污染,由於每一個模塊都至關於閉包,都存在於本身的命名空間模塊內的做用域。所以,外部沒法訪問內部私有變量,。

  3. 單一原則。每一個模塊內部都包含一個自執行函數,而這裏提供2個變量,一個exports,一個module,可是最後輸出的值,是在module.exports。

  4. 統一性,都使用module.exorts或exports來導出模塊,而後使用require()函數來導入模塊(同步)。

  5. 高度複用,能夠將別人的項目內某個功能之間導入使用。(前提是用module.exports或exports導出)。

缺點:

  1. 不兼容瀏覽器,不能直接使用。由於瀏覽器不支持global,module,require,exports這四個全局變量。

  2. 由於期初CommonJS的出現是應用在服務端,並且它的加載方式屬於同步的,注意,是加載時是同步的。所以,編碼時必須先去加載模塊,再執行,這樣會影響後面的代碼的執行時間,造成阻塞。


2. AMD

背景:

因爲出現了CommonJS規範,並且因爲NodeJS的推廣的緣由,使得JS在服務端大放光彩,能幹不少其餘語言能幹的事(java,python等)。

可是(AMD出現的緣由),這只是服務端的,畢竟客戶端仍是不能直接支持CommonJS規範的(至於爲何不支持查看CommonJS介紹)。而JS宿主就是以瀏覽器爲大頭的,哪能不行呢?

因此,時代造英雄,AMD英雄降臨了。

介紹:

AMD的出現主要解決客戶端的模塊化開發問題,並且 AMD又延續CommonJS規範的精神,都是模塊化開發,都是將模塊做用域定義在命名空間內,防止了全局變量的污染。

但同時也很大不同。

AMD:「由於我是異步加載模塊的!!!「

表明:

require.JS

解決了什麼問題?

AMD 定義了一套 JS 模塊依賴的異步加載標準,來解決同步加載的問題。

主要API:

  1. (導出) 定義模塊:
// 其實有不少方法,但該方法也是官網推薦用法:
	// 匿名定義模塊:
	define([依賴1,依賴2...],()=> {
		// 依賴加載完後,執行回調函數...
	})
複製代碼
  1. 導入模塊:
// 這點和commonJS的require有點不同,AMD須要2個參數,且有回調。
	const 變量 = require([模塊名],function() {
		// 執行回調操做...
	})
複製代碼

優勢:

  1. 模塊化,遵循CommonJS理念,一個文件即模塊。

  2. 低耦合,因爲採用命名空間內做用域有效,全部外部沒法訪問私有變量。

  3. 統一性,都由全局變量define函數(導出)定義模塊,全局變量require函數導入模塊。

  4. 高效性,因爲採用的是異步加載的方式來加載模塊,加載方法和CommonJS 「同樣「,都是使用require來加載模塊。可是AMD的require有點不同,AMD的require導入模塊時是異步的,並且語法是:require([依賴1,依賴2...],function() {})。也就是說,要先加載完全部依賴,才執行回調函數,而該回調回調函數的參數,也必須嚴格按照數組內的模塊順序來做爲參數,回調函數內都是依賴於這些模塊的邏輯代碼。那些和這些依賴無關的,能夠寫在外面,在加載依賴時,是不會影響接下來的代碼的。這也就對應了:異步加載,是不會影響後面的代碼的運行的。

缺點:

  1. 關係前置,我我的稱爲 「依賴前置「 。可能因爲設計思想的緣由,AMD雖然說是異步加載模塊,但倒是一次性加載完了對應模塊,再執行回調。雖然說沒毛病,我只有等我須要的裝備都齊了,才能打boss,這也說的過去。可是從人性化來看,就不怎麼好了,我但願我想加載哪一個的時候,再加載,不想加載的時候,你就別動。這點能夠查看下面CMD的優勢。

  2. 寫法比較輕浮,光是定義模塊就有好幾種寫法(雖然說官網有推薦寫法---定義模塊)。但這對初學者的我,會產生不少疑惑,也浪費了不少比較的時間。


3. CMD

介紹:

CMD,即Common Module Definition,通用模塊定義。

背景:

因爲AMD的出現,模塊化開發再也不是服務端獨有的了,瀏覽器也能實現模塊化開發了。但帶來便捷的同時,天然也有須要詬病的地方。 好比前面說的,因爲設計理念上,AMD是遵循 關係前置,也就是依賴前置的規範,來加載模塊。這就致使了一個問題,不夠人性化,體現不了按需加載的feel~

所以,國內牛人就AMD基礎上,出了個seaJS,同時在推廣過程,衍生出一種新的規範---CMD。 從字面意思就能大概猜出,CMD是比較貪心的啊,想作通用的規範哦。 但從語法上看,卻不是。 seaJS,其職責單一,嚴格遵循一個模塊就是一個文件的理念,是更接近CommonJS的理念的(具體哪一個理念本身查)。

上面說到就AMD基礎上出的seaJS,那就是有相同之處了,這裏只說不一樣之處。

CMD 特別就在於,體現了按需加載的理念。 能作到用同步的寫法,實現出按需加載的效果。 具體看下面API介紹。

主要API:

  1. define。 該全局變量是一個函數,該函數自帶3個參數,分別是require,exports,module,用來定義模塊用。 其和AMD相同的是,define函數均可以帶回調函數,都是能夠實現依賴前置的 。 但和AMD不一樣的是,遵循CMD規範的 JS ,是能夠 依賴後置 的,就是我能夠在回調函數裏再去加載模塊: 下面說明下三個參數(require, exports, module)的用處: (注意,在使用任何一種方法前,都把其餘方法註釋了!!!)
// 1. require:
	// 在定義時能夠去加載須要的依賴:
	define(function(require,exports,module) {
		// 按需加載模塊:
		let a = require(./b)
	})
	
	// 2. exports
	// exports 是一個對象,用來向外提供模塊接口:
	define(function(require,exports,module) {
		// 按需加載模塊:
		let a = require(./b)
		let a_obj = {
			a: a
		}
		// 導出方法:
		// 方法01:
		exports.a = a;
		// 或者導出一個function也是能夠的.

		// 方法02:
		// 使用return來直接代替exports
		return {
			a: a
		}
	
		// 這裏實例一個錯誤的寫法,歸納爲:不能直接給exports賦值,由於最後導出的是module.exports,這樣是不會改變模塊的值的:
		// 錯誤:
		exports = {
			a: a
		}
		// 正確:
		module.exports = {
			a: a
		}
	// 3. module:
	module.exports必須是同步執行,不能放在回調裏執行:
	// 好比定時器:
	// 錯誤用法
    setTimeout(function() {
      module.exports = { a: "hello" };
    }, 0);

})
複製代碼

優勢:

  1. 依賴後置,符合按需加載的設計理念,也符合SPA應用的首屏解決方案。
  2. 職責單一,理解簡單。

缺點:

  1. 能想到的估計就是API太普通了,簡直和AMD差很少的設計,學過require.JS的來㛑sea.js估計沒壓力,直接把數組去了,改成require了事了。

以爲我說的不對的歡迎掃描二維碼來告訴我,十分感謝!!!


我的公衆號二維碼
相關文章
相關標籤/搜索