JS JavaScript模塊化(ES Module/CommonJS/AMD/CMD)

前言

前端開發中,起初只要在script標籤中嵌入幾十上百行代碼就能實現一些基本的交互效果,後來js獲得重視,應用也普遍起來了,前端

jQuery,Ajax,Node.Js,MVC,MVVM等的助力也使得前端開發獲得重視,也使得前端項目愈來愈複雜,api

然而,JavaScript卻沒有爲組織代碼提供任何明顯幫助,甚至沒有類的概念,更不用說模塊(module)了,那麼什麼是模塊呢?瀏覽器

一個模塊就是實現特定功能的文件,有了模塊,咱們就能夠更方便地使用別人的代碼,想要什麼功能,就加載什麼模塊。服務器

 

1、AMD 規範

AMD 是 RequireJS 在推廣過程當中對模塊定義的規範化產出。app

模塊將被異步加載,模塊加載不影響後面語句的運行。異步

全部依賴某些模塊的語句均放置在回調函數中。async

 

用法:模塊化

  • 定義模塊:define(id?, dependencies?, factory)
  • 加載模塊:require([module], factory)
// a.js
// 依賴有三個默認的,即"require", "exports", "module"。順序個數都可視狀況
// 若是忽略則factory默認此三個傳入參數
// id通常是不傳的,默認是文件名
define(["b", "require", "exports"], function(b, require, exports) {
    console.log("a.js執行");
    console.log(b);
// 暴露api可使用exports、module.exports、return
    exports.a = function() {
        return require("b");
    }
})
// b.js
define(function() {
    console.log('b.js執行');
    console.log(require);
    console.log(exports);
    console.log(module);
    return 'b';
})
// index.js
// 支持Modules/Wrappings寫法,注意dependencies得是空的,且factory參數不可空
define(function(require, exports, module) {
    console.log('index.js執行');
    var a = require('a');
    var b = require('b');
})
// index.js
require(['a', 'b'], function(a, b) {
    console.log('index.js執行');
})

 

 

2、CMD 規範

CMD 是 SeaJS 在推廣過程當中對模塊定義的規範化產出。函數

在 CMD 規範中,一個模塊就是一個文件。requirejs

 

用法:

  • 定義模塊:define(factory)
/ require, exports, module參數順序不可亂
// 暴露api方法可使用exports、module.exports、return
// 與requirejs不一樣的是,如果未暴露,則返回{},requirejs返回undefined
define(function(require, exports, module) {
    console.log('a.js執行');
    console.log(require);
    console.log(exports);
    console.log(module);
})
// b.js
// 
define(function(require, module, exports) {
    console.log('b.js執行');
    console.log(require);
    console.log(exports);
    console.log(module);
})
// index.js
define(function(require) {
    var a = require('a');
    var b = require('b');
    console.log(a);
    console.log(b);
})

 

 

3、CommonJs 規範

CommonJs 是服務器端模塊的規範。

Node.js 採用了這個規範。Node.JS首先採用了js模塊化的概念。

根據 CommonJs 規範,一個單獨的文件就是一個模塊。每個模塊都是一個單獨的做用域,也就是說,在該模塊內部定義的變量,沒法被其餘模塊讀取,除非定義爲 global 對象的屬性。

 

用法:

  • 輸出模塊:module.exports
  • 加載模塊:require
// 導出使用module.exports,也能夠exports。exports指向module.exports;即exports = module.exports
// 就是在此對象上掛屬性
// commonjs
module.exports.add = function add(params) {
    return ++params;
}
exports.sub = function sub(params) {
    return --params;
}

// 加載模塊使用require('xxx')。相對、絕對路徑都可。默認引用js,能夠不寫.js後綴
// index.js
var common = require('./commonjs');
console.log(common.sub(1));
console.log(common.add(1));

 

 

4、ES Module

ES6 在語言標準的層面上,實現了模塊功能,成爲瀏覽器和服務器通用的模塊解決方案,徹底能夠取代 CommonJS 和 AMD 規範。

 

基本特色:

  • 每個模塊只加載一次, 每個JS只執行一次, 若是下次再去加載同目錄下同文件,直接從內存中讀取;
  • 每個模塊內聲明的變量都是局部變量, 不會污染全局做用域;
  • 模塊內部的變量或者函數能夠經過export導出;
  • 一個模塊能夠導入別的模塊

 

用法:

  • 輸出模塊:export
  • 加載模塊:import 
// module
export function fn1(){
    return  "這是 fn1";
}

export function fn2(){
    return "這是 fn2" ;
}

// main.js
//逐一加載
import { fn1, fn2 } from './module';

console.log( fn1());
console.log( fn2());

//總體加載
import * as all from './module';

console.log( all.fn1() );
console.log( all.fn2() );

 

 

動態加載模塊:

// 普通寫法
import('./module').then(({ a }) => {})
// async、await
const { a } = await import('./module');

 

 

5、各模塊之間的區別

一、CommonJS 與 AMD/CMD 的差別

  • CommonJS:是同步加載(代碼在本地,加載時間基本等於硬盤讀取時間)。
  • AMD / CMD:是異步加載

 

二、AMD 與 CMD 的差別

  • AMD是提早執行,CMD是延遲執行
  • AMD推薦依賴前置,CMD推薦依賴就近

 

三、CommonJS 與 ES Module 的差別

  • CommonJS 模塊是對象,是運行時加載,運行時才把模塊掛載在 exports 之上(加載整個模塊的全部),加載模塊其實就是查找對象屬性
  • ES Module 不是對象,是使用 export 顯示指定輸出,再經過 import 輸入,此法爲編譯時加載
  • CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用。
  • CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口

 

三、各模塊用法上的區別

  詳見各模塊介紹...

 

 

 

 

 

隨筆整理自
  https://www.jianshu.com/p/da2ac9ad2960
感謝博主分享!
相關文章
相關標籤/搜索