AMD,CMD,CommonJS,ES6區別與聯繫

1.AMD 是RequireJS 在推廣過程中對模塊定義的規範化產出(AMD 是提前執行),不過在requireJS的2.0開始也改成了延遲執行(寫法不同,處理方式不同)

        AMD 即Asynchronous Module Definition,中文名是“異步模塊定義”的意思。它是一個在瀏覽器端模塊化開發的規範,服務器端的規範是CommonJS。模塊將被異步加載,模塊加載不影響後面語句的運行。所有依賴某些模塊的語句均放置在回調函數中。

AMD規範只定義了一個函數 define,它是全局變量。函數爲:define(id,dependencies,factory);

define函數裏面的:

     id   (模塊名)

     是唯一確定的值,不可重複,可選。

     模塊名是用正斜槓分割的有意義的字符串,單詞爲駝峯命名法(或者 " . "  " , "  " .. " ),不允許文件擴展名

     模塊名可以是相對的或者頂級的, 如果首字符爲 " . "  " .. " 則爲相對的模塊名

     dependencies(依賴)

     是一個當前模塊依賴,模塊定義的模板標識的數字字面量。

     當然依賴參數也是可選的    它默認爲 [ 'require' , 'exports' , ' module ' ]  , 如果factory的長度屬性小於3,加載器會選擇以函數的長度屬性指定的參數個數調用factory方法

     factory(工廠方法)

     模塊初始化要是行的函數或者對象。依賴模塊必須根據模塊的factor優先級執行,並且執行的結果應該按照依賴數組組的位置順序傳入(定義模塊中)的工廠方法。如果爲函數,它應該只被執行一次。如果是對象,此對象應該爲模塊的輸出值。

創建一個id(模板名)爲“alpha”的模塊,使用了名爲:require,    exports,   beta  的模塊。

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
       exports.verb=function() {
           return beta.verb();
           //Or:returnrequire("beta").verb();
       }
   });

一個返回對象的匿名模塊:

   define(["alpha"], function (alpha) {
       return {
         verb:function(){
           return alpha.verb() +2;
         }
       };
   });

一個沒有依賴性的模塊可以直接定義對象:

   define({
     add:function(x, y){
       return x + y;
     }
   });

一個使用了簡單CommonJS轉換的模塊定義:

   define(function (require, exports, module) {
     var a =require('a'),
         b =require('b');

     exports.action=function () {};
   });

     

實現AMD的庫有RequireJS 、curl 、Dojo 、Nodules 等。

2.CMD 是 SeaJS 在推廣過程中對模塊定義的規範化產出。(CMD 是延遲執行

CMD 推崇依賴就近,AMD 推崇依賴前置

// CMD

 

define(function(require, exports, module) {

      // 依賴可以就近書寫

      var a = require('./a')

      a.doSomething()

 

     // 此處略去 1000 行

     var b = require('./b')

     b.doSomething()

    

})

// AMD 默認推薦的是:


define(['./a', './b'], function(a, b) {

    // 依賴必須一開始就寫好
     a.doSomething()


    // 此處略去 1000 行
    b.doSomething()
...
})

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

3.CommonJS模塊輸出的是一個值的拷貝,而且是在運行時加載

commonJS {

  module.exports =  ...   :      '只能輸出一個,且後面的會覆蓋上面的' ,

  exports. ...  : ' 可以輸出多個',

  運行階段確定接口,運行時纔會加載模塊,

  模塊是對象,加載的是該對象,

  加載的是整個模塊,即將所有的接口全部加載進來,

  輸出是值的拷貝,即原來模塊中的值改變不會影響已經加載的該值,

  this 指向當前模塊

}

commonJS是使用require來引入其他模塊的代碼,使用module.exports來引出:

//exportsDemo.js

count = 1;

module.exports.count = count;

module.exports.Hello = function() {

 var name;

 this.setName = function(newName) {

 name = newName;

 }

 this.sayHello = function() {

 console.log("hello Mr." + name);

 }

 this.getId = function() {

 return count++

 }

}

用require引入上面的模塊

// requireDemo.js

var {Hello} = require("./demo")

var hello = new Hello();

 

hello.setName("Blank");

hello.sayHello();

4.ES6模塊是編譯時輸出接口,也是輸出的值的引用

ES6模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。

ES6 模塊不會緩存運行結果,而是動態地去被加載的模塊取值,並且變量總是綁定其所在的模塊。

ES6的循環引用要特別注意變量是否已被聲明,若未被聲明的塊級作用域變量被其他模塊引用時,會報錯。

es6 {

  export   :      '可以輸出多個,輸出方式爲 {}' ,

  export  default : ' 只能輸出一個 ,可以與export 同時輸出,但是不建議這麼做',

  解析階段確定對外輸出的接口,解析階段生成接口,

  模塊不是對象,加載的不是對象,

  可以單獨加載其中的某個接口(方法),

  靜態分析,動態引用,輸出的是值的引用,值改變,引用也改變,即原來模塊中的值改變則該加載的值也改變,

  this 指向undefined

}

 

es6模塊中的值屬於【動態只讀引用】。只說明一下複雜數據類型。

對於只讀來說,即不允許修改引入變量的值,import的變量是隻讀的,不論是基本數據類型還是複雜數據類型。當模塊遇到import命令時,就會生成一個只讀引用。等到腳本真正執行時,再根據這個只讀引用,到被加載的那個模塊裏面去取值。

對於動態來說,原始值發生變化,import加載的值也會發生變化。不論是基本數據類型還是複雜數據類型。

// b.js

export let counter = {

      count: 1

}

setTimeout(() => {

        console.log('b.js-1', counter.count) }

, 1000

)

 

// a.js

import { counter } from './b.js'

counter = {}

console.log('a.js-1', counter)

雖然不能將counter重新賦值一個新的對象,但是可以給對象添加屬性和方法。此時不會報錯。這種行爲類型與關鍵字const的用法。

// a.js

import { counter } from './b.js'

counter.count++

console.log(counter)

 

循環加載時,ES6模塊是動態引用。只要兩個模塊之間存在某個引用,代碼就能夠執行。

 

// b.js

import {foo} from './a.js';

export function bar() {

       console.log('bar');

       if (Math.random() > 0.5) {

             foo();

        }

}

// a.js i

mport {bar} from './b.js';

export function foo() {

           console.log('foo');

           bar();

           console.log('執行完畢');

}

foo();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章