JavaScript模塊化與規(guī)范

一、什么是模塊化?

模塊化是指在解決某一個(gè)復(fù)雜問題或者一系列的雜糅問題時(shí),依照一種分類的思維把問題進(jìn)行系統(tǒng)性的分解以之處理。模塊化是一種處理復(fù)雜系統(tǒng)分解為代碼結(jié)構(gòu)更合理,可維護(hù)性更高的可管理的模塊的方式??梢韵胂笠粋€(gè)巨大的系統(tǒng)代碼,被整合優(yōu)化分割成邏輯性很強(qiáng)的模塊時(shí),對(duì)于軟件是一種何等意義的存在。對(duì)于軟件行業(yè)來(lái)說:解耦軟件系統(tǒng)的復(fù)雜性,使得不管多么大的系統(tǒng),也可以將管理,開發(fā),維護(hù)變得“有理可循”。

另一些對(duì)于模塊化一些專業(yè)的定義為:模塊化是軟件系統(tǒng)的屬性,這個(gè)系統(tǒng)被分解為一組高內(nèi)聚,低耦合的模塊。那么在理想狀態(tài)下我們只需要完成自己部分的核心業(yè)務(wù)邏輯代碼,其他方面的依賴可以通過直接加載被人已經(jīng)寫好模塊進(jìn)行使用即可。

既然是模塊化設(shè)計(jì),那么作為一個(gè)模塊化系統(tǒng)所必須的能力:

  • 定義封裝的模塊;
  • 定義新模塊對(duì)其他模塊的依賴;
  • 可對(duì)其他模塊的引入支持;

本篇,將市面上流行的幾種模塊化技術(shù)進(jìn)行對(duì)比,讓大家清楚具體的規(guī)范:

  • CommonJS(注意:不要與CMD混淆)
  • AMD(Asyncronous Module Definition)異步模塊定義
  • CMD(Common Module Definition)通用模塊定義
  • UMD(Universal Module Definition)通用模塊定義
  • ES6 module

二、規(guī)范

2.1、CommonJS

  • 特點(diǎn):
    • 一個(gè)單獨(dú)的文件就是一個(gè)模塊;
    • 可以多次加載,但只會(huì)在第一次加載時(shí)運(yùn)行一次,運(yùn)行結(jié)果被緩存;
    • 以后再加載,就直接讀取緩存結(jié)果;
    • 要想讓模塊再次運(yùn)行,必須清除緩存;
    • 模塊加載會(huì)阻塞后續(xù)代碼執(zhí)行,需要等到模塊加載完成才能繼續(xù)執(zhí)行(同步加載);
  • 環(huán)境:服務(wù)器環(huán)境
  • 應(yīng)用:nodejs的模塊規(guī)范是參照commonJS實(shí)現(xiàn)的
  • 語(yǔ)法:
    • 導(dǎo)入:require('路徑')
    • 導(dǎo)出:module.exports和exports
  • 注(module.exports和exports的區(qū)別):
    • exports只是module.exports的一個(gè)引用
    • 相當(dāng)于Node為每個(gè)模塊提供一個(gè)exports變量,指向module.exports
    • 同在每個(gè)模塊頭部,有一行var exports = module.exports;
 // a.js
 // 相當(dāng)于這里還有一行:var exports = module.exports;代碼
 exports.a = 'Hello world';  // 相當(dāng)于:module.exports.a = 'Hello world';

 // b.js
 var moduleA = require('./a.js');
 console.log(moduleA.a); // 打印出:hello world
---------------------------------------------------------------------------------
 // 稍微復(fù)雜點(diǎn)的例子
var $ = require('jquery');
var _ = require('underscore');

// methods
function a(){};    //    private because it's omitted from module.exports
function b(){};    //    public because it's defined in module.exports
function c(){};    //    public because it's defined in module.exports

// exposed public methods
module.exports = {
    b: b,
    c: c
};

2.2、AMD

  • 特點(diǎn):
    • 異步加載
    • 管理模塊之間的依賴性(多個(gè)JS文件依賴時(shí),依次加載最早被依賴的JS文件)
  • 環(huán)境:瀏覽器環(huán)境
  • 應(yīng)用:requireJS是參照AMD規(guī)范實(shí)現(xiàn)的
  • 語(yǔ)法:
    • 導(dǎo)入:require( ['模塊名稱'], function (模塊變量引用){ 代碼 } );
    • 導(dǎo)出:define(function (){return '值');
 // a.js
 define(function (){
   return {
    a:'hello world'
   }
 });

 // b.js
 require(['./a.js'], function (moduleA){
     console.log(moduleA.a); // 打印出:hello world
});
---------------------------------------------------------------------------------
// 稍微復(fù)雜點(diǎn)的例子
define(['jquery', 'underscore'], function ($, _) {
    // methods
    function a(){};    //    private because it's not returned
    function b(){};    //    public because it's returned
    function c(){};    //    public because it's returned

    // exposed public methods
    return {
        b: b,
        c: c
    }
});

2.3、CMD

  • 特點(diǎn):
    • CMD是在AMD基礎(chǔ)上改進(jìn)的一種規(guī)范;
    • 與AMD不同在于對(duì)依賴模塊的執(zhí)行時(shí)機(jī)處理不同:
    • CMD是就近依賴
    • AMD是前置依賴
  • 環(huán)境:瀏覽器環(huán)境
  • 應(yīng)用:seaJS是參照CMD規(guī)范實(shí)現(xiàn)的;requireJS最新幾個(gè)版本也參照了CMD規(guī)范;
  • 語(yǔ)法:
    • 導(dǎo)入:define(function(require, exports, module) {});
    • 導(dǎo)出:define(function (){return '值');
// a.js
define(function (require, exports, module){
  exports.a = 'hello world';
});

// b.js
define(function (require, exports, module){
    var moduleA = require('./a.js');
    console.log(moduleA.a); // 打印出:hello world
});

2.4、UMD

  • 特點(diǎn):
    • 兼容AMD和CommonJS規(guī)范的同時(shí),還兼容全局引用的方式;
  • 環(huán)境:瀏覽器環(huán)境
  • 應(yīng)用:無(wú)
  • 語(yǔ)法:無(wú)
(function (root, factory) {
     if (typeof define === 'function' && define.amd) {
         // AMD
         define(['jquery'], factory);
     } else if (typeof exports === 'object') {
         // Node, CommonJS之類的
         module.exports = factory(require('jquery'));
     } else {
         // 瀏覽器全局變量(root 即 window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
    //方法
    function myFunc(){};
    //暴露公共方法
    return myFunc;
}));
---------------------------------------------------------------------------------
// 稍微復(fù)雜點(diǎn)的例子
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery', 'underscore'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS-like
        module.exports = factory(require('jquery'), require('underscore'));
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.jQuery, root._);
    }
}(this, function ($, _) {
    // methods
    function a(){};    // private because it's not returned
    function b(){};    // public because it's returned
    function c(){};    // public because it's returned

    // exposed public methods
    return {
        b: b,
        c: c
    }
}));

2.5、ES6 module

  • 特點(diǎn):
    • 按需加載(編譯時(shí)加載)
    • import和export命令只能在模塊的頂層,不能在代碼塊之中
  • 環(huán)境:瀏覽器環(huán)境
  • 應(yīng)用:ES6最新語(yǔ)法支持規(guī)范;
  • 語(yǔ)法:
    • 導(dǎo)入:import {模塊名A,模塊名B...} from '模塊路徑';
    • 導(dǎo)出:export和export default
    • import('模塊路徑').then()方法
  • 注意:
    • export只支持對(duì)象形式導(dǎo)出,不支持值的導(dǎo)出
    • export default命令用于指定模塊的默認(rèn)輸出,只支持值導(dǎo)出
    • export default只能指定一個(gè),本質(zhì)上它就是輸出一個(gè)叫做default的變量或方法
/*錯(cuò)誤的寫法*/
 // 寫法一
 export 1;

 // 寫法二
 var m = 1;
 export m;

 // 寫法三
if (x === 2) {
  import MyModual from './myModual';
}

/*正確的三種寫法*/
// 寫法一
export var m = 1;

// 寫法二
var m = 1;
export {m};

// 寫法三
var n = 1;
export {n as m};

// 寫法四
var n = 1;
export default n;

// 寫法五
if (true) {
    import('./myModule.js')
    .then(({export1, export2}) => {
      // ...·
    });
}

// 寫法六
Promise.all([
  import('./module1.js'),
  import('./module2.js'),
  import('./module3.js'),
])
.then(([module1, module2, module3]) => {
   ···
});
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容