日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

AMD、CMD和Common规范

發布時間:2023/10/11 综合教程 101 老码农
生活随笔 收集整理的這篇文章主要介紹了 AMD、CMD和Common规范 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.名詞解釋
AMD:Asynchronous Modules Definition異步模塊定義,提供定義模塊及異步加載該模塊依賴的機制。
CMD:Common Module Definition 通用模塊定義,提供模塊定義及按需執行模塊

RequireJS 遵循 AMD(異步模塊定義)規范,Sea.js 遵循 CMD (通用模塊定義)規范。規范的不同,導致了兩者 API 不同。

2. 提前執行:提前異步并行加載
優點:盡早執行依賴可以盡早發現錯誤;缺點:容易產生浪費
3. 延遲執行:延遲按需加載
優點:減少資源浪費 缺點:等待時間長、出錯時間延后

2.1 AMD與CMD代碼模式

AMD代碼模式-運行策略

define(['./a', './b'], function(a, b) { //運行至此,a.js和b.js已經下載完成 a模塊和b模塊已經執行完,直接可用;
a.doing();
// 此處省略500行代碼
b.doing();
});

CMD代碼模式-運行策略

define(function(require, exports, module) {
var a = require("./a"); //等待a.js下載、執行完
a.doing();
// 此處省略500行代碼
var b = require("./b"); //依賴就近書寫
b.doing();
});

3. AMD 的 API 默認是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,沒有全局 require,而是根據模塊系統的完備性,提供 seajs.use 來實現模塊系統的加載啟動。CMD 里,每個 API 都簡單純粹。

方案 | 優勢 | 劣勢 | 特點
AMD | 速度快 | 會浪費資源 | 預先加載所有的依賴,直到使用的時候才執行
CMD | 只有真正需要才加載依賴 | 性能較差 | 直到使用的時候才定義依賴

它們除了希望放在瀏覽器作為loader也能夠放在服務端,提供加載功能。在我看來,AMD擅長在瀏覽器端、CMD擅長在服務器端。這是因為瀏覽器加載一個功能不像服務器那么快,有大量的網絡消耗。所以一個異步loader是更接地氣的。

或者,干脆使用YUI3的模塊機制,在上線前進行壓制。把互相依賴的模塊壓在一個文件中。

---------------------------------------------------------------------------------------------------

每一個卓越的思想都有一份樸實的代碼實現。所以無論AMD與CMD都要面臨以下幾個問題:

  1、模塊式如何注冊的,define函數都做了什么?
  2、他們是如何知道模塊的依賴?
  3、如何做到異步加載?尤其是seajs如何做到異步加載延遲執行的?
  辯證法第一規律:事物之間具有有機聯系。AMD與CMD都借鑒了CommonJs,宏觀層面必有一致性,比如整體處理流程:
  模塊的加載解析到執行過程一共經歷了6個步驟:
  1、由入口進入程序
  2、進入程序后首先要做的就是建立一個模塊倉庫(這是防止重復加載模塊的關鍵),JavaScript原生的object對象最為適合,key代表模塊Id,value代表各個模塊,處理主模塊
  3、向模塊倉庫注冊一模塊,一個模塊最少包含四個屬性:id(唯一標識符)、deps(依賴項的id數組)、factory(模塊自身代碼)、status(模塊的狀態:未加載、已加載未執行、已執行等),放到代碼中當然還是object最合適
  4、模塊即是JavaScript文件,使用無阻塞方式(動態創建script標簽)加載模塊

scriptElement= document.createElement('script');
scriptElement.src = moduleUrl;
scriptElement.async = true;
scriptElement.onload = function(){.........};
document.head.appendChild(scriptElement);

  5、模塊加載完畢后,獲取依賴項(amd、cmd區別),改變模塊status,由statuschange后,檢測所有模塊的依賴項。

  由于requirejs與seajs遵循規范不同,requirejs在define函數中可以很容易獲得當前模塊依賴項。而seajs中不需要依賴聲明,所以必須做一些特殊處理才能否獲得依賴項。方法將factory作toString處理,然后用正則匹配出其中的依賴項,比如出現require(./a),則檢測到需要依賴a模塊。

  同時滿足非阻塞和順序執行就需要需要對代碼進行一些預處理,這是由于CMD規范和瀏覽器環境特點所決定的。

  6、如果模塊的依賴項完全加載完畢(amd中需要執行完畢,cmd中只需要文件加載完畢,注意這時候的factory尚未執行,當使用require請求該模塊時,factory才會執行,所以在性能上seajs遜于requirejs),執行主模塊的factory函數;否則進入步驟3.

AMD規范定義了一個自由變量或者說是全局變量 define 的函數

define( id?, dependencies?, factory );

    第一個參數 id 為字符串類型,表示了模塊標識,為可選參數。若不存在則模塊標識應該默認定義為在加載器中被請求腳本的標識。如果存在,那么模塊標識必須為頂層的或者一個絕對的標識。
    第二個參數,dependencies ,是一個當前模塊依賴的,已被模塊定義的模塊標識的數組字面量。
    第三個參數,factory,是一個需要進行實例化的函數或者一個對象。
創建模塊標識為 alpha 的模塊,依賴于 require, export,和標識為 beta 的模塊  
  1. define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){
  2. export.verb = function(){
  3. return beta.verb();
  4. // or:
  5. return require("beta").verb();
  6. }
  7. });
    一個返回對象字面量的異步模塊
  1. define(["alpha"], function( alpha ){
  2. return {
  3. verb : function(){
  4. return alpha.verb() + 1 ;
  5. }
  6. }
  7. });
    無依賴模塊可以直接使用對象字面量來定義
  1. define( {
  2. add : function( x, y ){
  3. return x + y ;
  4. }
  5. } );
require();
在 AMD 規范中的 require 函數與一般的 CommonJS中的 require 不同。由于動態檢測依賴關系使加載異步,對于基于回調的 require 需求強烈。

局部 與 全局 的require

    局部的 require 需要在AMD模式中的 define 工廠函數中傳入 require。
  1. define( ['require'], function( require ){
  2. // ...
  3. } );
  4. or:
  5. define( function( require, exports, module ){
  6. // ...
  7. } );
    局部的 require 需要其他特定的 API 來實現。
    全局的 require 函數是唯一全局作用域下的變量,像 define一樣。全局的 require 并不是規范要求的,但是如果實現全局的 require函數,那么其需要具有與局部 require 函數 一樣的以下的限定:
    1. 模塊標識視為絕對的,而不是相對的對應另一個模塊標識。
    2. 只有在異步情況下,require的回調方式才被用來作為交互操作使用。因為他不可能在同步的情況下通過 require(String) 從頂層加載模塊。
    依賴相關的API會開始模塊加載。如果需要有互操作的多個加載器,那么全局的 reqiure 應該被加載頂層模塊來代替。
  1. require(String)
  2. define( function( require ){
  3. var a = require('a'); // 加載模塊a
  4. } );
  5. require(Array, Function)
  6. define( function( require ){
  7. require( ['a', 'b'], function( a,b ){ // 加載模塊a b 使用
  8. // 依賴 a b 模塊的運行代碼
  9. } );
  10. } );
  11. require.toUrl( Url )
  12. define( function( require ){
  13. var temp = require.toUrl('./temp/a.html'); // 加載頁面
  14. } );
define 和 require 這兩個定義模塊,調用模塊的方法合稱為AMD模式,定義模塊清晰,不會污染全局變量,清楚的顯示依賴關系。AMD模式可以用于瀏覽器環境并且允許非同步加載模塊,也可以按需動態加載模塊。
 
在CMD中,一個模塊就是一個文件,格式為:
    define( factory );
全局函數define,用來定義模塊。
    參數 factory  可以是一個函數,也可以為對象或者字符串。
    當 factory 為對象、字符串時,表示模塊的接口就是該對象、字符串。
    定義JSON數據模塊:
  1. define({ "foo": "bar" });
    通過字符串定義模板模塊:
  1. define('this is {{data}}.');
    factory 為函數的時候,表示模塊的構造方法,執行構造方法便可以得到模塊向外提供的接口。
  1. define( function(require, exports, module) {
  2. // 模塊代碼
  3. });
define( id?, deps?, factory );
    define也可以接受兩個以上的參數,字符串id為模塊標識,數組deps為模塊依賴:
  1. define( 'module', ['module1', 'module2'], function( require, exports, module ){
  2. // 模塊代碼
  3. } );
    其與 AMD 規范用法不同。
require 是 factory 的第一個參數。
    require( id );
    接受模塊標識作為唯一的參數,用來獲取其他模塊提供的接口:
  1. define(function( require, exports ){
  2. var a = require('./a');
  3. a.doSomething();
  4. });
    require.async( id, callback? );
    require是同步往下執行的,需要的異步加載模塊可以使用 require.async 來進行加載:
  1. define( function(require, exports, module) {
  2. require.async('.a', function(a){
  3. a.doSomething();
  4. });
  5. });
    require.resolve( id )
    可以使用模塊內部的路徑機制來返回模塊路徑,不會加載模塊。
    exports 是 factory 的第二個參數,用來向外提供模塊接口。
  1. define(function( require, exports ){
  2. exports.foo = 'bar'; // 向外提供的屬性
  3. exports.do = function(){}; // 向外提供的方法
  4. });
    當然也可以使用 return 直接向外提供接口。
  1. define(function( require, exports ){
  2. return{
  3. foo : 'bar', // 向外提供的屬性
  4. do : function(){} // 向外提供的方法
  5. }
  6. });
    也可以簡化為直接對象字面量的形式:
  1. define({
  2. foo : 'bar', // 向外提供的屬性
  3. do : function(){} // 向外提供的方法
  4. });
與nodeJS中一樣需要注意的是,一下方式是錯誤的:
  1. define(function( require, exports ){
  2. exports = {
  3. foo : 'bar', // 向外提供的屬性
  4. do : function(){} // 向外提供的方法
  5. }
  6. });
    需要這么做
  1. define(function( require, exports, module ){
  2. module.exports = {
  3. foo : 'bar', // 向外提供的屬性
  4. do : function(){} // 向外提供的方法
  5. }
  6. });
   傳入的對象引用可以添加屬性,一旦賦值一個新的對象,那么之前傳遞進來的對象引用就會失效了。開始之初,exports 是作為 module.exports 的一個引用存在,一切行為只有在這個引用上 factory 才得以正常運行,賦值新的對象后就會斷開引用,exports就只是一個新的對象引用,對于factory來說毫無意義,就會出錯。
    module 是factory的第三個參數,為一個對象,上面存儲了一些與當前模塊相關聯的屬性與方法。
        module.id 為模塊的唯一標識。
        module.uri 根據模塊系統的路徑解析規則得到模塊的絕對路徑。
        module.dependencies 表示模塊的依賴。
        module.exports 當前模塊對外提供的接口。
CommonJS
這種方式通過一個叫做require的方法,同步加載依賴,然后返導出API供其它模塊使用,一個模塊可以通過exports或者module.exports導出API。CommonJS規范中,一個單獨的文件就是一個模塊。每一個模塊都是一個單獨的作用域,在一個文件中定義的變量,都是私有的,對其他文件是不可見的。
Well
服務端模塊可以很好的復用
這種風格的模塊已經很多了,比如npm上基本上都是這種風格的module
簡單易用
Less Well
加載模塊是同步的,所以只有加載完成才能執行后面的操作
多個模塊不能并行加載
像Node.js主要用于服務器的編程,加載的模塊文件一般都已經存在本地硬盤,所以加載起來比較快,不用考慮異步加載的方式,所以CommonJS規范比較適用。但如果是瀏覽器環境,要從服務器加載模塊,這是就必須采用異步模式。所以就有了 AMD 、CMD 的解決方案。

CommonJS規范

 CommonJS是在瀏覽器環境之外構建JavaScript生態系統為目標產生的項目,比如服務器和桌面環境中。CommonJS規范是為了解決JavaScript的作用域問題而定義的模塊形式,
可以使每個模塊在它自身的命名空間中執行。該規范的主要內容是:模塊必須通過  module.exports導出對外的變量或接口,通過require()來導入其他模塊的輸出到當前模塊。
例子:
  1. // moduleA.js
  2. module.exports = function( value ){
  3. return value * 2;
  4. }
  1. // moduleB.js
  2. var multiplyBy2 = require('./moduleA');
  3. var result = multiplyBy2(4);

CommonJS是同步加載模塊,但其實也有瀏覽器端的實現,其原理是將所有模塊都定義好并通過id進行索引,這樣就可以瀏覽器進行解析了
 服務器端的Node.js遵循CommonJS規范。核心思想是允許模塊通過require 方法來同步加載所要依賴的其他模塊,然后通過 exports或module.exports來導出需要暴露的接口。

  1. require("module");
  2. require("../file.js");
  3. exports.doStuff = function() {};
  4. module.exports = someValue;
優點:
  • 服務器端便于重用
  • NPM中已經將近20w個模塊包
  • 簡單并容易使用
缺點:
  • 同步的模塊方式不適合不適合在瀏覽器環境中,同步意味著阻塞加載,瀏覽器資源是異步加載的
  • 不能非阻塞的并行加載多個模塊

AMD

AMD規范其實只有一個主要接口 define(id,dependencies,factory),它要在聲明模塊的時候指定所有的依賴dependencies,并且還要當做形參傳到factory中,對于依賴的模塊提前執行,依賴前置
  1. define("module", ["dep1", "dep2"], function(d1, d2) {
  2. return someExportedValue;
  3. });
  4. require(["module", "../file"], function(module, file) { /* ... */ });

優點:

  • 適合在瀏覽器環境異步加載
  • 并行加載多個模塊
缺點:
  • 提高開發成本,代碼閱讀和書寫比較困難
  • 不符合通用的模塊思維方式,是一種妥協的實現

CMD

CMD規范和AMD相似,盡量保持簡單,并且與CommonJS和NodeJS的Modules規范保持了很大的兼容性。

  1. define(function(require, exports, module) {
  2. var $ = require('jquery');
  3. var Spinning = require('./spinning');
  4. exports.doSomething = ...
  5. module.exports = ...
  6. })

優點:

  • 依賴就近,延遲執行
  • 很容易在node中運行
缺點:
  • 依賴SPM打包,模塊的加載邏輯偏重

總結

以上是生活随笔為你收集整理的AMD、CMD和Common规范的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。