模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等。
第一阶段:IIFE (立即执行函数)
// 定义module
var myModule = (function(){
var var1 = 1;
var var2 = 2;
function fn1(){}
function fn2(){}
return {
fn1,
fn2
};
})();
// 调用module
myModule.fn1()
myModule.fn2()
第二阶段:CommonJS规范
CommonJS 规范最开始用在服务器端的 Node 中。
根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性。
CommonJS的核心思想就是通过 require 方法来同步加载所要依赖的其他模块,然后通过 exports 或者 module.exports 来导出需要暴露的接口
。
var fs = require('fs');
exports.age = 22;
module.exports = {
name: 'Jim'
}
缺点:
由于 CommonJS 是同步加载模块的,在服务器端,文件都是保存在硬盘上,所以同步加载没有问题,但是对于浏览器端,需要将文件从服务器端请求过来,那么同步加载就不适用了,所以,CommonJS是不适用于浏览器端的。
第三阶段:AMD规范
AMD 规范是异步加载模块,允许指定回调函数。浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。而AMD规范的实现,就是大名鼎鼎的require.js
了。
特点:依赖前置(依赖必须提前声明好)
定义 person 模块:
// package/lib 就是依赖
define(['package/lib'], function(lib) {
// lib就是package/lib返回的内容
function foo() {
lib.log('hello world');
}
return {
foo: foo
}
});
引入模块:
require(['person'], function (person) {
person.foo();
});
第四阶段:CMD规范
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出,是一个同步模块定义,是SeaJS的一个标准,SeaJS是CMD概念的一个实现。
优点:可以按需加载,依赖就近。
define(function(require, exports, module) {
// 通过require引入依赖
var $ = require('jquery');
var index = require('./index');
exports.obj = {age: 20}
});
通过 define 定义,没有依赖前置,通过 require 加载模块,是一个同步的概念。
其实,这时我们就可以看出AMD和CMD的区别了,前者是对于依赖的模块提前执行,而后者是延迟执行。 前者推崇依赖前置,而后者推崇依赖就近,即只在需要用到某个模块的时候再require。
第五阶段:UMD规范
同时兼容 AMD,CommonJS 模块化语法。
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS之类的
module.exports = factory(require('jquery'));
} else {
// 浏览器全局变量(root 即 window)
root.returnExports = factory(root.jQuery);
}
}(this, function ($) {
// 方法
function myFunc(){};
// 暴露公共方法
return myFunc;
}));
第六阶段:ES6 Modules
ES6 引入的模块化,使用 import,export,export default 来导入导出模块。
import a from 'a';
const name = 'Jim';
export const age = 22;
export {
name
}
<script type="module"></script>