JavaScript的四種模塊化規范

  1. <b>CommonJS規范</b>

    由于ES5沒有模塊化規范,所以產生了這三種規范。在ES6中又新增了一種公用模塊化的方法。

    特點:同步

    CommonJS規范是通過module.exports定義的,在前端瀏覽器中并不支持此中規范

    瀏覽器不兼容Common的根本原因也就是缺少四個Node環境的變量

    • module
    • exports
    • require
    • global

    Node以及Webpack是采用CommonJS的形式來寫的

    CommonJS定義的模塊分為三種:模塊引用(require);模塊定義(exports);模塊標識(module)

    require()用來引入外部模塊,exports對象用于導出當前模塊,或者當前的模塊的方法和變量,module對象代表對象本身

    var foo = require('foo.js');
    var count =1;
    var plus = ()=>{
       foo.add(count);
    };
    module.exports= {
       count,
       plus
    }
    

    <b>特點</b>

    ? 對于基本數據類型,和語言本身一樣屬于復制,即會被模塊緩存,在另一個模塊中可以對該模塊輸出的變量重新賦值。

    ? 對于復雜數據類型,例如Array,Object,屬于淺拷貝,即同時指向一個內存空間,因此對一個模塊的值的改變可以影響另一個模塊。詳見javascript深拷貝與淺拷貝詳解。

    當使用require命令加載同一個模塊時,不會再執行該模塊,而是取到緩存之中的值。也就是說,CommonJS模塊無論加載多少次,都只會在第一次加載時運行一次,以后再加載,就返回第一次運行的結果,除非手動清除系統緩存。

    <b>循環加載</b>

    // a.js
    exports.done = false
    let b = require('./b.js')
    console.log('a.js-1', b.done)
    exports.done = true
    console.log('a.js-2', '執行完畢')
    
    // b.js
    exports.done = false
    let a = require('./a.js')
    console.log('b.js-1', a.done)
    exports.done = true
    console.log('b.js-2', '執行完畢')
    
    // c.js
    let a = require('./a.js')
    let b = require('./b.js')
    
    console.log('c.js-1', '執行完畢', a.done, b.done)
    
    

    運行node c.js

    usr:~ usr$  node c.js
    b.js-1 false
    b.js-2 執行完畢
    a.js-1 true
    a.js-2 執行完畢
    c.js-1 執行完畢 true true
    

    循環加載時,commonjs屬于加載時執行,即腳本代碼在require時候,就會全部執行。一旦出現某個模塊被“循環加載”,只輸出已經執行的部分,未執行的部分不輸出。

    上述代碼很明顯的表現出了此類特點

    step1: node c.js

    step2: require(./a.js) //執行完a.js中的內容

    step2.1: export.done = flase; let b = require(./b.js); // 執行b中的代碼

    step2.2: export.done = flase; let a= require(./a.js) //由于發生了循環加載,所以只執行a中的第一句,然后繼續執行b.js 輸出 <code>b.js-1 false b.js-2執行完畢</code>

    step2.3: 繼續執行b中的代碼 將b.done 賦值為true

    step 2.4 : 執行a的剩余部分 a.js-1 true; a.js-2 執行完畢

    step3:require(./b.js) 由于已經執行過了不會再執行b中的代碼 所以直接輸出b返回值

    step4: 輸出c.js-1 執行完畢 true true


  2. <b>AMD規范</b>

    由于CommonJS的局限性 例如

    var math = require('math');
    
    math.add(2,3);
    

    第二行代碼必須要在 require之后運行,如果math加載時間很長,就會陷入空等,整個過程是同步的。

    對于服務器這不是個問題,因為都存儲在本地,但是對于客戶端,如果由于網絡原因,可能會陷入“假死”狀態。

    所以客戶端,不能采用同步加載,只能使用異步加載。

    AMD規范是require.js對模塊化定義的一種規范化產出

    ? 模塊本身和模塊之間的引用可以被異步加載

    ? 先引入模塊后使用模塊的方法,稱之為<b>依賴前置</b>

    優點

    ? 1.包括異步調用和本身高擴展性

    ? 2.解耦,模塊在代碼中也可以通過識別號進行查找

    define(['./package/lib.js'], function(lib) {
          function say(){
               lib.log('this is fn');
           }
           return {
               say:say
           }; 
    });
    

    Tips

    ? lib.js是我們引入的方法,回調中lib參數表示的是引入的模塊的所有方法及屬性

    ? 我們在當前模塊定義了say方法,并且return say的執行結果

  3. <b>CMD規范</b>

    SeaJs

    CMD:同步模塊定義

    依賴就近原則

    sayHello.js

    define(function(require,exports,module){
       //通過require引入依賴,并不是AMD的依賴前置,而是依賴就近,哪里用,哪里引
       //例如下列引入jquery
       var JQ = require('jquery');
       exports.sayHello = function(){
           $('#hello').toggle('slow')
       }
    })
    

    main.js

    define(function(require){
       var CMD = require('sayHello');
       var temp = new CMD();
       temp.sayHello();
    })
    
  4. <b>ES6模塊化規范</b>

    ES6在語言標準上面實現了模塊功能。設計思想是盡量的靜態化,使得編譯時就能確定模塊的依賴關系,以及輸入輸出變量。CommonJS以及AMD都只能在運行時確定

    ES6的模塊并不是對象,而是通過export顯示指定輸出的代碼,再通過import命令導入

    //commonJs
    // CommonJS模塊
    let { stat, exists, readFile } = require('fs');
    
    // 等同于
    let _fs = require('fs');
    let stat = _fs.stat;
    let exists = _fs.exists;
    let readfile = _fs.readfile;
    //創建了一個對象
    
    //ES6
    import { stat, exists, readFile } from 'fs';
    

    上面代碼的實質是從fs模塊加載 3 個方法,其他方法不加載。這種加載稱為“編譯時加載”或者靜態加載,即 ES6 可以在編譯時就完成模塊加載,效率要比 CommonJS 模塊的加載方式高。當然,這也導致了沒法引用 ES6 模塊本身,因為它不是對象。

    export輸出的接口,是變量實時的值,與commonjs輸出的是值的緩存不相同

    export與import要出現在模塊頂層

    如果想要重新命名,需要使用as關鍵字

    也可以引入整個模塊

    import * as bb from './xxx'

    也可以匿名導出 這樣可以給導出的模塊任意指定名字

    export default

    import anyname from 'xx.js'

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。