CMD,AMD,CommonJS,ES6 Module学习笔记

127 阅读3分钟

最近在面试以及工作中因为经常会涉及到模块化的问题,就去查了模块化的相关资料,今天就来大致的做一个总结。

为什么会有模块化的出现呢?

首先,在早期时,javascript是没有模块化的定义的,后面代码量增多了就得分成多个文件,需要依次加载js文件(如下所示)

<script src="1.js"></script>
......
<script src="2.js"></script>

这种写法的缺点就是,因为浏览器中加载js引擎和渲染引擎之间是互斥的,加载js时会停止渲染网页,如果加载时间过程很可能会导致白屏现象,其次如果各个文件之间有依赖,就必须按照顺序来执行,后期也会难以维护。

AMD

AMD--"Asynchronous Module Definition"(异步模块定义)。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。 AMD规范通过define方法去定义模块,通过require方法去加载模块。下面代码贴出它的相关用法:

```//独立模块(module1.js)
define({
        method1: function() {
            console.log('我是module1');
        },
        method2: function() {
            console.log('我是module2')
        },
});
//第二种写法:作为函数return出去(module2.js)
define(function () {
    return {
        method1: function() {
            console.log('我是module1');
        },
        method2: function() {
            console.log('我是module2')
        },
    };
});
//非独立组件,依赖于其他组件,第一个参数是一个数组(包含其依赖的模块),第二个参数是一个函数
define(['module1', 'module2'], function(m1, m2) {// 依赖必须一开始就写好
    return{
        module:function(){
            m1.methodA();
            ..........
            m2.methodB();
        }
    }
 });
 //定义一个main.js,去加载这些模块
 define(['module2'],function(m2){
    m2.method3();
})

CMD

CMD--"Common Module Definition",在CMD规范里面,一个模块就是一个Javascript文件。

define(function(require, exports, module) {
var a = require('module1')
a.method1()
.......
var b = require('module2') // 依赖可以就近书写
b.method1()
})

AMD与CMD的区别

  1. 以上我们可以从代码中看出对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible。(尽可能的懒加载)
  2. CMD 推崇依赖就近,AMD 推崇依赖前置。(从代码中可以看出)

CommonJS

CommonJS规范,一个单独的文件就是一个模块。CommonJS是2009年由JavaScript社区提出的包含了模块化的一个标准,后来被Node.js所采用并实现,也就是说我们在Node.js中用到的模块导入导出都是依照CommonJS标准来实现的。

var md=function(){
    console.log('hello,commonjs');
}
// 1.通过exports.xxx = xxx导出 exports.test=md
// 2.通过module.exports.xxx = xxx导出 module.exports.test=md
exports.test=md
//同目录下新建一个test.js文件
var module=require("./module");
//调用
module.test();
//执行
node test.js

ES6 Module

JavaScript在ES6加入了模块(module)体系的语法,ES6主要提供两个命令export和import,用于模块向外提供接口(export)和引入其他模块接口(import)。

//导出(A.js)
let a=1
function fn(){}
//1.命名导出
export{a,fn}//批量导出
export let a=1
export function fn(){}//单个的导出
//2.默认导出
export default fn
//导入(B.js)
import {fn, a} from './A.js'
import {fn as fn1, a as count} from './A.js'//(通过as来进行重命名)
import * as module from './A.js'//(通过*来整体导出,并赋值给module,再通过module来调用)
import fn1 from './A.js'//(针对默认导出的对象,所以只能有一个默认导出的对象)

ES6 Module与CommonJS的区别

  1. 对于模块的依赖,CommonJS是动态的(运行时加载),ES6 Module 是静态的(编译时输出接口)
  2. CommonJS导入的是值的拷贝(拷贝后的值改变不会影响之前值的改变),ES6 Module导入的是值的引用(会影响之前的值)
  3. CommonJSthis指向当前模块,ES6 Modulethis指向undefined;

最后:本文只是做一个大致介绍,纯属记录个人笔记,也引用了网上的相关资料,更多细节感兴趣的可以自行查阅资料,小白第一次写文章,若有不妥的地方欢迎吐槽。