JS模塊化的梳理

CommonJS

Node應用使用CommonJS模塊規範,Node中每一個文件就是一個模塊,有本身的做用域,在模塊中定義的變量
、函數都是私有的。html

模塊中有四個重要的變量globalmoduleexportsrequire前端

Node中的全局變量global,和瀏覽器的window對象相似,聲明在全局下的變量能夠在全部模塊中訪問。module變量表明當前模塊,其中module.exports屬性表示當前模塊對外輸出的接口,當其餘文件使用require引用該模塊時,實際就是讀取module.exports變量。vue

// 模塊a.js
const num = 1
module.exports = {
    num,
    add: function(x,y){
        return x+y
    }
}
//模塊b.js,引入a.js
const a = require('./a.js')
// {num:1, add:fn}

exports變量是對module.exports的引用;至關於在頂部聲明一個變量var exports = module.exportsexports不能直接賦值,這樣就沒法指向module.exports
因此使用exports對外輸出接口的寫法以下,jquery

// 模塊a.js
exports.num = 1
exports.add = function(x,y){
    return x+y
}
CommonJS規範加載模塊是同步的,加載完成之後,才能執行後面的操做。同時模塊輸出的是值的拷貝,也就是說,一旦輸出一個值,模塊內部的變化就影響不到這個值。

AMD

AMD:Asynchronous Module Definition,異步模塊定義,是RequireJS在推廣過程當中對模塊定義的規範化產出。require.js加載完成後,經過回調方法加載data-main中的js,而後require.config方法指定第三方資源路徑,define方法來定義本身寫的模塊,最後使用require方法加載模塊webpack

<!-- 引入require.js,main.js中配置require.config -->
<script src="require.js" data-main="main.js"></script>

<!-- main.js -->
<script>
    require.config({
        paths: {
            "Vue": "./vue",
            "jquery": "./jquery"  //js後綴不寫
        }
    })
    require(["Vue","jquery"],function(vue,$){
        // 依賴的模塊會以參數的形式傳進回調函數,這裏就能夠正常使用Vue和jQuery了
    })
</script>

define方法自定義模塊,不須要在require.config裏配置路徑es6

<!-- 本身的模塊好比:module_test.js -->
<script>
    define(function(){
        function add(x,y){
            return x+y
        }
        return {
            add
        }
    })
</script>
<!-- 若是自定義依賴其餘模塊,先引入其餘模塊 -->
<script>
    define(['jquery'],function($){
        function add(x,y){
            const total = x+y
            $('body').html(total)
            return total
        }
        return {
            add
        }
    })
</script>

CMD

CMD:Common Module Definition,通用模塊定義, 是SeaJS在推廣過程當中對模塊定義的規範化產出。和AMD語法相似,區別是AMD在定義模塊的時候就要聲明其依賴的模塊,而CMD只有在用到某個模塊的時候再去加載。AMDCMD都實現了前端資源的模塊的,而如今ES6和Webpack打包工具的出現這兩個應該使用比較少了。web

ES6 Module

ES6在語言標準的層面上,實現了模塊功能。模塊功能主要由兩個命令構成:exportimportexport命令用於規定模塊的對外接口,import命令用於輸入其餘模塊提供的功能。咱們平時的項目通常都是基於webpack來處理,若是想直接在瀏覽器中加載ES6模塊,和原來同樣使用<script>便籤,同時須要添加type="module"屬性。瀏覽器

參考Module的加載實現緩存

// m1.js定義輸出
const a = 1
export default a
export const b = 2
export function add(x,y){
    return x+y
}

// m2.js引用
import a, {b, add} from './m2.js'

ES6模塊與CommonJS模塊的兩大差別異步

  • 一、CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用;
  • 二、CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口。

ES6模塊中的原始值變了,import加載的值也會跟着變。所以,ES6 模塊是動態引用,而且不會緩存值,模塊裏面的變量綁定其所在的模塊。

UMD

UMD是AMD和CommonJS的糅合,UMD會先判斷是否支持Node.js模塊的exports,再判斷AMD的define方法是否存在,最後都不支持的話就掛載在window全局變量下。
好比打開Vue.js文件

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? 
    module.exports = factory() :
  // 是否支持Node.js模塊   
  typeof define === 'function' && define.amd ? 
    define(factory) :
  // 是否支持AMD
  (global = global || self, global.Vue = factory());
  // 最後都不行掛載在window.Vue
}(this, function () { 
    'use strict';
}))
相關文章
相關標籤/搜索