• CommonJS
    Node.js提供了四个环境变量来对模块化的支持,分别是:module、exports、require、global。module.exports来定义当前模块对外部输出的接口。在外部文件引入当前文件时使用require来加载模块。NOde.js的模块加载是同步的。具体请看:node模块;下面我们来简单实现一下CommonJS的模块和引用

    1
    2
    3
    4
    // math.js
    const a = 1;
    const add = (a, b) => a + b;
    module.exports = {a, add}

    以上我们在math.js文件中定义了一个常量a和一个add方法,然后我们使用module.exports对外导出该模块的变量。接下来我们在a.js文件中使用require方法来引用math.js模块对外导出的接口

    1
    2
    3
    4
    5
    //a.js
    const math = require('./math'); // require('./math.js') 两种写法是相同的
    console.log(math.a); // 1;
    const results = math.add(1,2);
    console.log(results); // 3

    如上所示,我们在a.js文件中引入了math模块。并且使用该模块的对外接口进行了相应的计算。CommonJS加载模块的方式是同步的方式,在服务器端,模块文件是存放在内存中,其io读取的速度是非常快的,但是如果放在浏览器中,我们需要考虑到网络的原因,所以使用异步加载模块是更加合理的选择。

  • AMD
    AMD使用异步方式来处理模块的加载,在程序中该模块的加载不会影响后续代码的运行,但是依赖该加载的模块执行的代码都被定义在一个回调函数中,等到该模块加载完成之后,其回调函数中的代码才是会被执行。以下使用require.js来实现AMD模块加载。使用require.js来实现AMD采用require.config来配置模块的一些信息。用require()来加载require.config中配置的模块。为了在文件中能够使用AMD模块,首先我们先在项目的入口文件中引入require.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <script src='./thirds/require.js'></script>

    // 在main.js中定义各个模块内容的路径以及模块的别名
    require.config({
    baseUrl: 'js/lib',
    paths: {
    'jquery': 'jquery.min', // 最后输出的路径是: js/lib/jquery.min.js
    '_': 'underscore.min'
    }
    });

    // a.js
    require(["jquery", "_"], function($, _){
    console.log($);
    console.log(_);
    })

    从上面我们知道,使用require来加载模块的时候,我们将需要引用的模块名放入到[]数组中。将要引入的文件模块的全局变量放入到require函数的第二个参数函数内作为该函数的参数名。我们在定义模块的时候,如果我们的模块本身依赖其他的模块,那么我们就需要将这些依赖的模块放在[]数组中作为defin()函数的第一个参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // math.js;不依赖其他的模块
    defin(function(){
    const a = 1;
    const add = (a, b) => a + b;
    return {
    a,
    add
    }
    })

    // other.js模块依赖underscore模块
    defin(["underscore"], function(_) {
    return {
    countBy: _.countBy
    }
    })

    如上,我们分别定义了两个AMD模块,其中一个模块不依赖其他的任何模块,因此不需要[]来包含其他的模块,后面的other模块依赖_模块,因此需要在[]中引入该模块。在其他的文件中引入的方式同上面a.js引入的方式一样。

  • CMD
    CMD是另外的一种模块化实现方式,与AMD相似,但是AMD是依赖前置,提前执行,CMD是就近依赖,延迟执行。典型的CMD规范就是sea.js

    1
    2
    3
    4
    5
    6
    7
    8
    // CMD写法
    defin(function(require, exports, module){
    const math = require('./math'); // 在需要使用该模块的时候才引用该模块
    math.add(1, 2);

    // 导出模块
    exports.add = math.add;
    })
  • ES6 Module
    ES6 module主要是使用两个命令构成: exportimport。export命令用于导出该模块对外的接口,import命令用于输入导出的模块提供的接口

    1
    2
    3
    4
    // math.js
    const a = 1;
    const add = (a, b) => a + b;
    export {a, add}

    在a.js中引入math.js导出的模块

    1
    2
    3
    4
    // a.js
    import {a, add} from './math'
    const results = add(1, 2);
    console.log(results); // 3

    ES6的模块还提供了一个export default命令来导出默认的模块。与之对应的是在引入该模块的文件中引入该模块时不需要使用大括号

    1
    2
    3
    4
    // math.js
    const a = 1;
    const add = (a, b) => a + b;
    export default {a, add}

    在a.js中以如下的方式引用和使用

    1
    2
    3
    4
    // a.js
    import math from './math'
    const results = math.add(1, 2);
    console.log(results); // 3