CommonJS、AMD、CMD以及ES6的模块系统

371 阅读2分钟

1.同步CommonJS

主要用于服务端node.js

//定义 test.js
var x = 10;    
var funcA = function(value) {return value;};
module.exports.x = x;
module.exports.funcA = funcA;

//使用 test.js
var test = require(‘./test‘);
test.funcA(2);
console.log(test.x) 

//定义模块math.js
var basicNum = 0;
function add(a, b) {
    return a + b;
}
module.exports = { //在这里写上需要向外暴露的函数、变量
    add: add,
    basicNum: basicNum
}

//使用 math.js 引用自定义的模块时,参数包含路径,可省略.js
var math = require(‘./math‘);
math.add(2, 5);

//引用核心模块时,不需要带路径
var http = require(‘http‘);
http.createService(...).listen(3000); 

exports和module.exports区别:

  • exports:对于本身来讲是一个变量(对象),它不是module的引用,它是{}的引用。
  • exports指向module.exports的{}模块,只能使用.语法 向外暴露变量。

module.exports:

  • module是一个变量,指向一块内存。
  • exports是module中的一个属性,存储在内存中,然后exports属性指向{}模块。
  • 既可以使用.语法,也可以使用=直接赋值。

2.异步

由于CommonJS是同步代码,但是客户端大多都需要异步加载

异步加载库:

  • RequireJS (AMD) 运行前先申明,提前加载
  • SeaJS (CMD已倒闭) 运行后申明,懒加载

AMD => RequireJS

属于 AMD 推崇依赖前置、提前执行

  • 1.使用require.config()定义特征
  • 2.用definde()定义模块
  • 3.用require()加载模块
//require.config定义:
require.config({
  baseUrl: "js/lib",
  paths: {
    "jquery": "jquery.min",  //实际路径为js/lib/jquery.min.js
    "math": "math.min",
  }
});
// 定义math.js模块
define(function(){  xxxx; }); 
// 引入模块模块
require(['jquery','math'],function($, math){  });

CMD => CMD 或 sea.js

CMD推崇依赖就近、延迟执行

/** CMD写法 **/
define(function(require, exports, module) {
    var a = require(‘./a‘); //在需要时申明
    a.doSomething();
    if (false) {
        var b = require(‘./b‘);
        b.doSomething();
    }
});

/** sea.js **/
// 定义模块 math.js
define(function(require, exports, module) {
    var $ = require(‘jquery.js‘);
    var add = function(a,b){
        return a+b;
    }
    exports.add = add;
});
// 加载模块
seajs.use([‘math.js‘], function(math){
    var sum = math.add(1+2);
}); 

3.ES6的模块系统

export 输出:变量,函数,类
export default (模块的默认值)
// a.js
export let a = 1          //输出变量
export fn(){...}          //输出函数
export class Class{
  constructor(a,b){
    this.a = a;
    this.b = b;
  }
}                         //输出类

fn2(){...}                //定义一个函数
export fn2;               //建议以这种在末尾统一输出的方式export
export {fn2 ,fn};         //导出多个变量,要有{}
export {fn2 as asFn2};    //导出时重命名,要有{}


// b.js
import {fn2} from 'a.js';  //export 的引入要加{},单个也要加;
import {fn2 , a , Class as Class1}  from 'a.js'   //引入多个要用 ‘,’隔开;
import * as example from 'a.js';                  //引入整个模块
example.a = 1;                                    //使用模块,在有很多需要引入时,建议这种方法;

// a.js
export default function(num1,num2){...}   //导出默认值,只能导出一个
export let a = 1;                         //导出变量a
  
// b.js
import any from 'a.js';                   //引入默认值,any 可以是任意的名字,不用{}
import {a} from 'a.js';                   //引入a ;
import any,{a} from 'a.js'                //默认值必须放在非默认值前面
import {default as any , a} from 'a.js'   //有重命名就要大括号包起来