JavaScript模塊化

參考探索js的模塊化

什么是JavaScript模塊化?

模塊化在我看來,就是把一些公共的函數(shù)封裝起來給其他地方調(diào)用,而不用重復(fù)去寫一些冗余的函數(shù)代碼。

JavaScript模塊化大致發(fā)展過程

CommonJS(服務(wù)端) => AMD (瀏覽器端) => CMD / UMD => ES Module

CommonJS

CommonJS主要用于服務(wù)器端。 這個(gè)規(guī)范是同步的

特點(diǎn):
  • 模塊可以多次加載,首次加載的結(jié)果將會(huì)被緩存,想讓模塊重新運(yùn)行需要清除緩存。

  • 模塊的加載是一項(xiàng)阻塞操作,也就是同步加載。

      // a.js
      module.exports = {
        moduleFunc: function() {
          return true;
        };
      }
      // 或
      exports.moduleFunc = function() {
        return true;
      };
    
      // 在 b.js 中引用
      var moduleA = require('a.js');
      // 或
      var moduleFunc = require('a.js').moduleFunc;
    
      console.log(moduleA.moduleFunc());
      console.log(moduleFunc())
    

AMD規(guī)范

在commonJS中, 模塊的加載過程是一個(gè)同步的過程, 很明顯地,如果在瀏覽器端, 肯定就會(huì)引起瀏覽器頁面的阻塞,因此,這時(shí)候?qū)δK異步加載的需求就出現(xiàn)了。從而出現(xiàn)AMD規(guī)范

異步模塊定義規(guī)范(AMD)制定了定義模塊的規(guī)則,這樣模塊和模塊的依賴可以被異步加載。這和瀏覽器的異步加載模塊的環(huán)境剛好適應(yīng)(瀏覽器同步加載模塊會(huì)導(dǎo)致性能、可用性、調(diào)試和跨域訪問等問題)

這時(shí)候RequireJS應(yīng)運(yùn)而生

RequireJS

特點(diǎn):
  • 前置依賴,異步加載

  • 便于管理模塊之間的依賴性,有利于代碼的編寫和維護(hù)。

      // a.js
      define(function (require, exports, module) {
        console.log('a.js');
        exports.name = 'Jack';
      });
    
      // b.js
      define(function (require, exports, module) {
        console.log('b.js');
        exports.desc = 'Hello World';
      });
    
      // main.js
      require(['a', 'b'], function (moduleA, moduleB) {
        console.log('main.js');
        console.log(moduleA.name + ', ' + moduleB.desc);
      });
    
      // 執(zhí)行順序:
      // a.js
      // b.js
      // main.js
    

然而, 他也有他的不足之處
按照 AMD 的規(guī)范,在定義模塊的時(shí)候需要把所有依賴模塊都羅列一遍(前置依賴),而且在使用時(shí)還需要在 factory 中作為形參傳進(jìn)去。

define(['a', 'b', 'c', 'd', 'e', 'f', 'g'], function(a, b, c, d, e, f, g){ ..... });

是不是看起來又丑又復(fù)雜。。

RequireJS 模塊化的順序是這樣的:模塊預(yù)加載 => 全部模塊預(yù)執(zhí)行 => 主邏輯中調(diào)用模塊,所以實(shí)質(zhì)是依賴加載完成后還會(huì)預(yù)先一一將模塊執(zhí)行一遍,這種方式會(huì)使得程序效率有點(diǎn)低。

這個(gè)時(shí)候就出現(xiàn)了CMD規(guī)范,典型的就是seajs模塊化

SeaJS

SeaJS 模塊化的順序是這樣的:模塊預(yù)加載 => 主邏輯調(diào)用模塊前才執(zhí)行模塊中的代碼,通過依賴的延遲執(zhí)行,很好解決了 RequireJS 被詬病的缺點(diǎn)。

    // a.js
    define(function (require, exports, module) {
      console.log('a.js');
      exports.name = 'Jack';
    });

    // main.js
    define(function (require, exports, module) {
      console.log('main.js');
      var moduleA = require('a');
      console.log(moduleA.name);
    });

    // 執(zhí)行順序
    // main.js
    // a.js

ES6的module

ES Module 的思想是盡量的靜態(tài)化,即在編譯時(shí)就確定所有模塊的依賴關(guān)系,以及輸入和輸出的變量,和 CommonJS 和 AMD/CMD 這些標(biāo)準(zhǔn)不同的是,它們都是在運(yùn)行時(shí)才能確定需要依賴哪一些模塊并且執(zhí)行它。ES Module 使得靜態(tài)分析成為可能

  • 模塊功能主要由兩個(gè)命令構(gòu)成:export 和 import。export 命令用于規(guī)定模塊的對(duì)外接口,import 命令用于輸入其他模塊提供的功能。

  • 通過 export 命令定義了模塊的對(duì)外接口,其他 JS 文件就可以通過 import 命令加載這個(gè)模塊。

      模塊的定義
      /**
       * export 只支持對(duì)象形式導(dǎo)出,不支持值的導(dǎo)出,export default 命令用于指定模塊的默認(rèn)輸出,
       * 只支持值導(dǎo)出,但是只能指定一個(gè),本質(zhì)上它就是輸出一個(gè)叫做default 的變量或方法
       */
      // 寫法 1
      export var m = 1;
      // 寫法 2
      var m = 1;
      export { m };
      // 寫法 3
      var n = 1;
      export { n as m };
      // 寫法 4
      var n = 1;
      export default n;
    
     模塊的引入
      // 解構(gòu)引入
      import { firstName, lastName, year } from 'a-module';
      // 為輸入的變量重新命名
      import { lastName as surname } from 'a-module';
      // 引出模塊對(duì)象(引入所有)
      import * as ModuleA from 'a-module';
    

在使用 ES Module 值得注意的是:import 和 export 命令只能在模塊的頂層,在代碼塊中將會(huì)報(bào)錯(cuò)
這是因?yàn)?ES Module 需要在編譯時(shí)期進(jìn)行模塊靜態(tài)優(yōu)化,import 和 export 命令會(huì)被 JavaScript 引擎靜態(tài)分析,先于模塊內(nèi)的其他語句執(zhí)行,這種設(shè)計(jì)有利于編譯器提高效率,但也導(dǎo)致無法在運(yùn)行時(shí)加載模塊(動(dòng)態(tài)加載)。

最后編輯于
?著作權(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)容