JavaSript模塊規範 - AMD規範與CMD規範介紹

来源:http://www.cnblogs.com/liboxncg/archive/2016/11/11/6054936.html
-Advertisement-
Play Games

模塊化是指在解決某一個複雜問題或者一系列的雜糅問題時,依照一種分類的思維把問題進行系統性的分解以之處理。模塊化是一種處理複雜系統分解為代碼結構更合理,可維護性更高的可管理的模塊的方式。可以想象一個巨大的系統代碼,被整合優化分割成邏輯性很強的模塊時,對於軟體是一種何等意義的存在。對於軟體行業來說:解耦... ...


JavaSript模塊化

      在瞭解AMD,CMD規範前,還是需要先來簡單地瞭解下什麼是模塊化,模塊化開發?       模塊化是指在解決某一個複雜問題或者一系列的雜糅問題時,依照一種分類的思維把問題進行系統性的分解以之處理。模塊化是一種處理複雜系統分解為代碼結構更合理,可維護性更高的可管理的模塊的方式。可以想象一個巨大的系統代碼,被整合優化分割成邏輯性很強的模塊時,對於軟體是一種何等意義的存在。對於軟體行業來說:解耦軟體系統的複雜性,使得不管多麼大的系統,也可以將管理,開發,維護變得“有理可循”。       還有一些對於模塊化一些專業的定義為:模塊化是軟體系統的屬性,這個系統被分解為一組高內聚,低耦合的模塊。那麼在理想狀態下我們只需要完成自己部分的核心業務邏輯代碼,其他方面的依賴可以通過直接載入被人已經寫好模塊進行使用即可。   首先,既然是模塊化設計,那麼作為一個模塊化系統所必須的能力:     1. 定義封裝的模塊。     2. 定義新模塊對其他模塊的依賴。     3. 可對其他模塊的引入支持。       好了,思想有了,那麼總要有點什麼來建立一個模塊化的規範制度吧,不然各式各樣的模塊載入方式只會將局攪得更為混亂。那麼在JavaScript中出現了一些非傳統模塊開發方式的規範 CommonJS的模塊規範,AMD(Asynchronous Module Definition),CMD(Common Module Definition)等。

AMD 與 RequireJS

AMD

    Asynchronous Module Definition,用白話文講就是 非同步模塊定義,對於 JSer 來說,非同步是再也熟悉不過的詞了,所有的模塊將被非同步載入,模塊載入不影響後面語句運行。所有依賴某些模塊的語句均放置在回調函數中。       AMD規範定義了一個自由變數或者說是全局變數 define 的函數。  

    define( id?, dependencies?, factory );    

    AMD規範  https://github.com/amdjs/amdjs-api/wiki/AMD     第一個參數 id 為字元串類型,表示了模塊標識,為可選參數。若不存在則模塊標識應該預設定義為在載入器中被請求腳本的標識。如果存在,那麼模塊標識必須為頂層的或者一個絕對的標識。     第二個參數,dependencies ,是一個當前模塊依賴的,已被模塊定義的模塊標識的數組字面量。     第三個參數,factory,是一個需要進行實例化的函數或者一個對象。       創建模塊標識為 alpha 的模塊,依賴於 require, export,和標識為 beta 的模塊  
define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){
    export.verb = function(){
        return beta.verb();
        // or:
        return require("beta").verb();
    }
});
      一個返回對象字面量的非同步模塊
define(["alpha"], function( alpha ){
    return {
        verb : function(){
            return alpha.verb() + 1 ;
        }
    }
});
    無依賴模塊可以直接使用對象字面量來定義
define( {
    add : function( x, y ){
        return x + y ;
    }
} );
    類似與 CommonJS 方式定義
define( function( require, exports, module){
    var a = require('a'),
          b = require('b');
    exports.action = function(){};
} );

    require();  

    require API 介紹 https://github.com/amdjs/amdjs-api/wiki/require       在 AMD 規範中的 require 函數與一般的 CommonJS中的 require 不同。由於動態檢測依賴關係使載入非同步,對於基於回調的 require 需求強烈。  

    局部 與 全局 的require

    局部的 require 需要在AMD模式中的 define 工廠函數中傳入 require。
define( ['require'], function( require ){
  // ...
} );
or:
define( function( require, exports, module ){
  // ...
} );
      局部的 require 需要其他特定的 API 來實現。     全局的 require 函數是唯一全局作用域下的變數,像 define一樣。全局的 require 並不是規範要求的,但是如果實現全局的 require函數,那麼其需要具有與局部 require 函數 一樣的以下的限定:     1. 模塊標識視為絕對的,而不是相對的對應另一個模塊標識。     2. 只有在非同步情況下,require的回調方式才被用來作為交互操作使用。因為他不可能在同步的情況下通過 require(String) 從頂層載入模塊。     依賴相關的API會開始模塊載入。如果需要有互操作的多個載入器,那麼全局的 reqiure 應該被載入頂層模塊來代替。  
require(String)
define( function( require ){
    var a = require('a'); // 載入模塊a
} );
require(Array, Function)
define( function( require ){
    require( ['a', 'b'], function( a,b ){ // 載入模塊a b 使用
        // 依賴 a b 模塊的運行代碼
    } ); 
} );
require.toUrl( Url )
define( function( require ){
    var temp = require.toUrl('./temp/a.html'); // 載入頁面
} );
    amdjs 的API   https://github.com/amdjs/amdjs-api/wiki

RequireJS

    官網 http://www.requirejs.org/     API http://www.requirejs.org/docs/api.html       RequireJS 是一個前端的模塊化管理的工具庫,遵循AMD規範,它的作者就是AMD規範的創始人 James Burke。所以說RequireJS是對AMD規範的闡述一點也不為過。       RequireJS 的基本思想為:通過一個函數來將所有所需要的或者說所依賴的模塊實現裝載進來,然後返回一個新的函數(模塊),我們所有的關於新模塊的業務代碼都在這個函數內部操作,其內部也可無限制的使用已經載入進來的以來的模塊。  
  1. <script data-main='scripts/main' src='scripts/require.js'></script>
    那麼scripts下的main.js則是指定的主代碼腳本文件,所有的依賴模塊代碼文件都將從該文件開始非同步載入進入執行。       defined用於定義模塊,RequireJS要求每個模塊均放在獨立的文件之中。按照是否有依賴其他模塊的情況分為獨立模塊和非獨立模塊。     1. 獨立模塊,不依賴其他模塊。直接定義:
define({
    method1: function(){},
    method2: function(){}
});
    也等價於
define(function(){
    return{
        method1: function(){},
        method2: function(){}
    }
});
      2. 非獨立模塊,對其他模塊有依賴。
define([ 'module1', 'module2' ], function(m1, m2){
    ...
});
    或者:
define( function( require ){
    var m1 = require( 'module1' ),
          m2 = require( 'module2' );
    ...
});
      簡單看了一下RequireJS的實現方式,其 require 實現只不過是將 function 字元串然後提取 require 之後的模塊名,將其放入依賴關係之中。       require方法調用模塊       在require進行調用模塊時,其參數與define類似。
require( ['foo', 'bar'], function( foo, bar ){
    foo.func();
    bar.func();
} );
    在載入 foo 與 bar 兩個模塊之後執行回調函數實現具體過程。       當然還可以如之前的例子中的,在define定義模塊內部進行require調用模塊
define( function( require ){
    var m1 = require( 'module1' ),
          m2 = require( 'module2' );
    ...
});
    define 和 require 這兩個定義模塊,調用模塊的方法合稱為AMD模式,定義模塊清晰,不會污染全局變數,清楚的顯示依賴關係。AMD模式可以用於瀏覽器環境並且允許非同步載入模塊,也可以按需動態載入模塊。  

CMD 與 seaJS

CMD

    在CMD中,一個模塊就是一個文件,格式為:     define( factory );       全局函數define,用來定義模塊。     參數 factory  可以是一個函數,也可以為對象或者字元串。     當 factory 為對象、字元串時,表示模塊的介面就是該對象、字元串。       定義JSON數據模塊:
  1. define({ "foo": "bar" });
    通過字元串定義模板模塊:
define('this is {{data}}.');
    factory 為函數的時候,表示模塊的構造方法,執行構造方法便可以得到模塊向外提供的介面。
define( function(require, exports, module) { 
    // 模塊代碼
});
    define( id?, deps?, factory );     define也可以接受兩個以上的參數,字元串id為模塊標識,數組deps為模塊依賴:
define( 'module', ['module1', 'module2'], function( require, exports, module ){
    // 模塊代碼
} );
    其與 AMD 規範用法不同。       require 是 factory 的第一個參數。     require( id );     接受模塊標識作為唯一的參數,用來獲取其他模塊提供的介面:
define(function( require, exports ){
    var a = require('./a');
    a.doSomething();
});
    require.async( id, callback? );     require是同步往下執行的,需要的非同步載入模塊可以使用 require.async 來進行載入:
define( function(require, exports, module) { 
    require.async('.a', function(a){
        a.doSomething();
    });
});
    require.resolve( id )     可以使用模塊內部的路徑機制來返回模塊路徑,不會載入模塊。       exports 是 factory 的第二個參數,用來向外提供模塊介面。
define(function( require, exports ){
    exports.foo = 'bar'; // 向外提供的屬性
    exports.do = function(){}; // 向外提供的方法
});
    當然也可以使用 return 直接向外提供介面。
define(function( require, exports ){
    return{
        foo : 'bar', // 向外提供的屬性
        do : function(){} // 向外提供的方法
    }
});
    也可以簡化為直接對象字面量的形式:
define({
    foo : 'bar', // 向外提供的屬性
    do : function(){} // 向外提供的方法
});
    與nodeJS中一樣需要註意的是,一下方式是錯誤的:
define(function( require, exports ){
    exports = {
        foo : 'bar', // 向外提供的屬性
        do : function(){} // 向外提供的方法
    }
});
    需要這麼做
define(function( require, exports, module ){
    module.exports = {
        foo : 'bar', // 向外提供的屬性
        do : function(){} // 向外提供的方法
    }
});
    傳入的對象引用可以添加屬性,一旦賦值一個新的對象,那麼值錢傳遞進來的對象引用就會失效了。開始之初,exports 是作為 module.exports 的一個引用存在,一切行為只有在這個引用上 factory 才得以正常運行,賦值新的對象後就會斷開引用,exports就只是一個新的對象引用,對於factory來說毫無意義,就會出錯。       module 是factory的第三個參數,為一個對象,上面存儲了一些與當前模塊相關聯的屬性與方法。         module.id 為模塊的唯一標識。         module.uri 根據模塊系統的路徑解析規則得到模塊的絕對路徑。         module.dependencies 表示模塊的依賴。         module.exports 當前模塊對外提供的介面。

seaJS

    官網 http://seajs.org/docs/     API快速參考 https://github.com/seajs/seajs/issues/266
    sea.js 核心特征:         1. 遵循CMD規範,與NodeJS般的書寫模塊代碼。         2. 依賴自動載入,配置清晰簡潔。     相容 Chrome 3+,Firefox 2+,Safari 3.2+,Opera 10+,IE 5.5+。       seajs.use      用來在頁面中載入一個或者多個模塊
// 載入一個模塊 
seajs.use('./a');
// 載入模塊,載入完成時執行回調
seajs.use('./a',function(a){
    a.doSomething();
});
// 載入多個模塊執行回調
seajs.use(['./a','./b'],function(a , b){
    a.doSomething();
    b.doSomething();
});
      其define 與 require 使用方式基本就是CMD規範中的示例。  

AMD 與 CMD 區別到底在哪裡?

      看了以上 AMD,requireJS 與 CMD, seaJS的簡單介紹會有點感覺模糊,總感覺較為相似。因為像 requireJS 其並不是只是純粹的AMD固有思想,其也是有CMD規範的思想,只不過是推薦 AMD規範方式而已, seaJS也是一樣。       下麵是玉伯對於 AMD 與 CMD 區別的解釋:       AMD 是 RequireJS 在推廣過程中對模塊定義的規範化產出。     CMD 是 SeaJS 在推廣過程中對模塊定義的規範化產出。       類似的還有 CommonJS Modules/2.0 規範,是 BravoJS 在推廣過程中對模塊定義的規範化產出還有不少??         這些規範的目的都是為了 JavaScript 的模塊化開發,特別是在瀏覽器端的。     目前這些規範的實現都能達成瀏覽器端模塊化開發的目的。         區別:         1. 對於依賴的模塊,AMD 是提前執行,CMD 是延遲執行。不過 RequireJS 從 2.0 開始,也改成可以延遲執行(根據寫法不同,處理方式不同)。CMD 推崇 as lazy as possible.       2. CMD 推崇依賴就近,AMD 推崇依賴前置。看代碼:
// CMD
define(function(require, exports, module) {
    var a = require('./a')
    a.doSomething()
    // 此處略去 100 行
    var b = require('./b') // 依賴可以就近書寫
    b.doSomething()
    // ...
})
// AMD 預設推薦的是
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好
    a.doSomething()
    // 此處略去 100 行
    b.doSomething()
    // ...
})
  雖然 AMD 也支持 CMD 的寫法,同時還支持將 require 作為依賴項傳遞,但 RequireJS 的作者預設是最喜歡上面的寫法,也是官方文檔里預設的模塊定義寫法。       3. AMD 的 API 預設是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,沒有全局 require,而是根據模塊系統的完備性,提供 seajs.use 來實現模塊系統的載入啟動。CMD 里,每個 API 都簡單純粹。       4. 還有一些細節差異,具體看這個規範的定義就好,就不多說了。   另外,SeaJS 和 RequireJS 的差異,可以參考:https://github.com/seajs/seajs/issues/277   原文地址:http://blog.chinaunix.net/uid-26672038-id-4112229.html
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 微軟基礎類庫(英語:Microsoft Foundation Classes,簡稱MFC)是一個微軟公司提供的類庫(class libraries),以C++類的形式封裝了Windows API,並且包含一個應用程式框架,以減少應用程式開發人員的工作量。其中包含的類包含大量Windows句柄封 ...
  • 問題:兩張表互為外鍵約束,刪除任何一張表都會出錯 解決方法:臨時關閉檢查 語法:set @@foreign_key_checks=OFF; OK,然後就可以推倒你親手種的果了,各種姿勢drop ps:資料庫設計寧可多花點兒時間,準沒錯。 walker花了一周的時間寫個小項目練手,沒想到今天突然發現底 ...
  • 一、前言 結合我們本次系列的第一篇博文中提到的上下文映射圖(傳送門:如何一步一步用DDD設計一個電商網站(一)—— 先理解核心概念),得知我們這個電商網站的核心域就是銷售子域。因為電子商務是以信息網路技術為手段,以商品交換為中心的商務活動,一個好的核心域設計可以大大提升企業的競爭力和對市場變化的相應 ...
  • http://v3.bootcss.com/ 這個國內的中文站點資料很全 如下看個頁面的大體框架 http://www.cnblogs.com/sunhaoyu/p/4275190.html <!-- bootstarp 的導航欄預設高度為 50px class="nav navbar-invers ...
  • js簡單的歸納 js簡單的歸納 基本類型 number,string,boolean,null,undefined 組合類型 一種對象類型: object 數組 函數 對象 正則 關於函數 作用域 閉包 構造函數 原型鏈 關於對象 類 類的繼承 實例方法 靜態方法 私有方法 運算符 算術 邏輯 關係 ...
  • .factory('iParamsServices', function () { var map = {}; return { get: function (key) { return map[key]; }, put: function (key, object) { map[key] = ob ...
  • 淘寶的 NPM 鏡像是一個完整的npmjs.org鏡像。你可以用此代替官方版本(只讀),同步頻率目前為 15分鐘 一次以保證儘量與官方服務同步。(對於國內的有需求的人真是福音) 有興趣的童鞋可以去https://npm.taobao.org/瞭解一下。 使用說明 你可以使用定製的 cnpm (gzi ...
  • 1、WebStorm快捷鍵: Ctrl+Alt+(向下方向鍵):快速複製當前行 Alt+(向上/下方向鍵):移動當前行 Ctrl+D:刪除當前行 Ctrl+/:快速(取消)註釋當前行 Ctrl+Alt+L:格式化當前文檔2、HTML5九大新特性: ①表單新特性、②視頻音頻、③Canvas繪圖、④SV ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...