什么是模块化
- 模块化可以提高代码复用率,方便进行代码的管理
- 模块化主要是用来抽离公共代码,私有作用域,避免变量冲突等
- 目前流行的js模块化规范有CommonJS、AMD、CMD以及ES6的模块系统
区别
-
Node.js采取CommonJS规范,因为是服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,可以采取同步加载模块
-
浏览器端一般采用AMD规范,浏览器环境要从服务器端加载模块,这时就必须采用异步模式,出的早,可以指定回调函数
-
CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。CMD规范整合了CommonJS和AMD规范的特点
-
RequireJS是一个工具库,主要用于客户端的模块管理。它的模块管理遵守AMD规范,RequireJS的基本思想是,通过define方法,将代码定义为模块;通过require方法,实现代码的模块加载。
-
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
-
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
commonJS
// 暴露模块:module.exports = value或exports.xxx = value
var x = 5;
var addX = function (value) {
return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
// 引入模块:require(模块名或模块文件路径)
var example = require('./example.js')
console.log(example.x) // 5
console.log(example.addX(1)) // 6
特点
-
私有模块作用域,不会污染全局作用域
-
加载模块是同步的,按照其在代码中出现的顺序
-
模块可以多次加载,有缓存。第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存
-
模块的加载机制,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。多个模块取值会影响。
AMD
// AMD是异步加载模块,允许指定回调函数// 定义暴露模块: 没有依赖的模块
define(function(){
return 模块
})// 定义暴露模块: 有依赖的模块
define(['module1', 'module2'], function(m1, m2){
return 模块
})
// 引入使用模块:
require(['module1', 'module2'], function(m1, m2){
使用m1/m2
})
CMD
// CMD模块使用时才会加载执行
// 定义暴露模块:没有依赖的模块
define(function(require, exports, module){
exports.xxx = value
module.exports = value
})
// 定义暴露模块:有依赖的模块
define(function(require, exports, module){
//引入依赖模块(同步)
var module2 = require('./module2')
//引入依赖模块(异步)
require.async('./module3', function (m3) {
})
//暴露模块
exports.xxx = value
})
//引入使用模块:
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
ES6模块化
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
// export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
// 定义模块 math.js
var basicNum = 0;
var add = function (a, b) {
return a + b;
};
export { basicNum, add };
// 引用模块
import { basicNum, add } from './math';
function test(ele) {
ele.textContent = add(99 + basicNum);
}