32_什么是模塊化開發?談下AMD、CMD、CommonJs和ES6的區別

一、模塊化開發

什么是模塊化

所謂的模塊化開發就是封裝細節,提供使用接口,彼此之間互不影響,每個模塊都是實現某一特定的功能。模塊化開發的基礎就是函數

1、使用函數封裝

function func1(){
    //...
}
function func2(){
    //...
}

上面的函數func1 ()和func2 (),組成一個模塊。使用的時候,直接調用就行了。這種做法的缺點很明顯:"污染"了全局變量,無法保證不與其他模塊發生變量名沖突,而且模塊成員之間看不出直接關系。

2、使用對象封裝

為了解決上面的缺點,可以把模塊寫成一個對象,所有的模塊成員都放到這個對象里面。

var obj = {
    age : 0,
    func1 : function (){
        //...
    },
    func2 : function (){
        //...
    }
};

上面的函數func1 ()和func2 (),都封裝在obj對象里。使用的時候,就是調用這個對象的屬性。

obj.func1();

這樣做也是有問題的,變量可以被外面隨意改變而導致不安全。比如,年齡被修成負數。

obj.age = -100;

如何保證對象的屬性不被訪問了?

3、立即執行函數寫法

使用"立即執行函數"(Immediately-Invoked FunctionExpression,IIFE),可以達到不暴露私有成員的目的。這個也是閉包處理的一種方式。

var obj= (function(){
    var _age= 0;
    var func1= function(){
      //...
    };
    var func2= function(){
      //...
    };
    return {
      m1 : func1,
      m2 : func2
    };
})();

使用上面的寫法,外部代碼無法讀取內部的age變量。

console.info(obj.age);//undefined

4、放大模式

如果一個模塊很大,必須分成幾個部分,或者一個模塊需要繼承另一個模塊,這時就有必要采用"放大模式"(augmentation)。在原有的基礎上擴展更多的方法。

var obj =(function (mod){
    mod.func3 = function () {
      //...
    };
    return mod;//方便方法連續調用
})(obj);

上面的代碼為obj模塊添加了一個新方法func3 (),然后返回新的obj模塊,方便方法連續調用。如何防止obj為null或undefined的情況? 可以采用寬放大模式。

5、寬放大模式(Loose augmentation)

在瀏覽器環境中,模塊的各個部分通常都是從網上獲取的,有時無法知道哪個部分會先加載。如果采用上面的寫法,第一個執行的部分有可能加載一個不存在的空對象,這時就要采用"寬放大模式"。

var obj =( function (mod){
    //...
    return mod;
  })(window.obj|| {});//確保對象不為空

與"放大模式"相比,"寬放大模式"就是"立即執行函數"的參數可以是空對象,解決了非空問題。

6、輸入全局變量

獨立性是模塊的重要特點,模塊內部最好不與程序的其他部分直接交互。為了在模塊內部調用全局變量,必須顯式地將其他變量輸入模塊。

(function(window, undefined ) {
  ……
})(window);

這是jQuery框架的源碼,將window對象作為參數傳入,這樣做除了保證模塊的獨立性,還使得模塊之間的依賴關系變得明顯。

目前,通行的JavaScript模塊規范共有兩種:CommonJS和AMD。

二、AMD、CMD、CommonJs、ES6的對比

他們都是用于在模塊化定義中使用的,AMD、CMD、CommonJs是ES5中提供的模塊化編程的方案,import/export是ES6中定義新增的

1、AMD-異步模塊定義

AMD是RequireJS在推廣過程中對模塊定義的規范化產出,它是一個概念,RequireJS是對這個概念的實現,就好比JavaScript語言是對ECMAScript規范的實現。AMD是一個組織,RequireJS是在這個組織下自定義的一套腳本語言 例:

define(['package/lib'], function(lib){ 
  function foo(){
    lib.log('hello');
    return {
        foo: foo
    };
});

RequireJS:是一個AMD框架,可以異步加載JS文件,按照模塊加載方法,通過define()函數定義,第一個參數是一個數組,里面定義一些需要依賴的包,第二個參數是一個回調函數,通過變量來引用模塊里面的方法,最后通過return來輸出。

:RequireJS是一個依賴前置、異步定義的AMD框架(在參數里面引入js文件),在定義的同時如果需要用到別的模塊,在最前面定義好即在參數數組里面進行引入,在回調里面加載

2、CMD-同步模塊定義

CMD是SeaJS在推廣過程中對模塊定義的規范化產出,是一個同步模塊定義,是SeaJS的一個標準,SeaJS是CMD概念的一個實現,SeaJS是淘寶團隊提供的一個模塊開發的js框架. 例:

define(function(require,exports,module){
  //通過require 引入依賴(依賴就近原則)
  var $ = require('jquery');
  var Spinning = require('./spinning');
}

通過define()定義,沒有依賴前置,通過require加載jQuery插件,CMD是依賴就近,在什么地方使用到插件就在什么地方require該插件,即用即返,這是一個同步的概念

3、CommonJS規范

CommonJS規范是通過module.exports定義的,在前端瀏覽器里面并不支持module.exports,通過node.js后端使用的。Nodejs端是使用CommonJS規范的,前端瀏覽器一般使用AMD、CMD、ES6等定義模塊化開發的

exports.area = function (r) {
  return Math.PI * r * r;
};

exports.circumference = function (r) {
  return 2 * Math.PI * r;
};

輸出方式有2種:

  • 默認輸出---module.exports
  • 帶有名字的輸出---exports.func

4、ES6特性,模塊化

AMD,CMD,CommoJs都是ES5里面的規范,下面的export/import是ES6里面的規范。通過export/import輸入輸出 例:

export default {
    props:['name'],
    data () {
        return{ }
    },
    methods:{
        increment(){
            this.$emit('incre');
            import('./../until')
        },
        decrement(){
            this.$emit('decre');
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。