js模块化
一、Module模式
最初js使用模块设计模式来解决全局作用域污染的问题(利用闭包和匿名函数自调用)
let modele = (function(window){
let mName = "modulename"
function setM(name){
mName =name
}
function getM(){
return mName
}
return {setM,getM}
})(window)
二、模块规范化
1、CommonJS
主要用于Node服务端开发,每个文件都是一个模块,有自己的作用域,使用module.exports暴露变量,使用require()引入模块
-
使用同步加载,在执行时按顺序加载模块,执行时不再加载模块
-
模块的输出时对值的拷贝,输出后的值无法影响模块内的值
-
可以多次加载,但只会在第一次加载时运行加载依赖,之后会缓存,以后直接读取缓存,要再运行必须清除缓存
-
CommonJS始终只会导出一个默认成员
// a.js var x = 5; var addX = function (value) { return value + x; }; module.exports.x = x; module.exports.addX = addX;
2、AMD规范
异步加载,使用 define(‘modle’, [加载资源], ()=>{})定义模块,使用require引入模块,但是,在使用require.js的时候,必须要提前加载所有的依赖,然后才可以使用
-
异步加载,可用于浏览器端
-
使用起来比较复杂
-
模块js文件请求频繁
-
前置加载,不能按需加载
define(function () {
var alertName = function (str) {
alert("I am " + str);
}
var alertAge = function (num) {
alert("I am " + num + " years old");
}
return {
alertName: alertName,
alertAge: alertAge
};
});
require(['alert'], function (alert) {
alert.alertName('JohnZhu');
alert.alertAge(21);
});
3、CMD规范
阿里提出的,实现js库为sea.js,使用define定义模块,使用exports暴露模块,使用require定义模块
- 异步加载,可用于浏览器端
- 实现按需加载,依赖就近,延迟执行
- 需要依赖SPM打包,模块加载逻辑偏重
AMD与CMD区别:
- CMD:加载依赖提前执行,依赖前置
- AMD:加载依赖延迟执行,依赖就近(用到时在require)
// AMD
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
});
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b')
// 依赖可以就近书写
b.doSomething()
// ...
});
4、ESmodule
ES6新增的模块化规范,可用于浏览器端和服务端,使用export暴露,使用import导入模块,在script标签中设置type为module就可以使用此规范
- 异步加载
- 自动使用严格模式
- 通过CORS请求外部模块
- script标签会延迟执行模块
- 动态引入,引入后值的改变会影响到原来的值,导入的其实时值的内存地址
- ES module可以导入CommonJS模块,CommonJS不能导入ES module模块
- 多对象输出,多对象加载
import a from '../a.js'
export default{
function b{
return 1+2
}
}
参考 JavaScript模块化 之( Commonjs、AMD、CMD、ES6 modules)演变史 - 简书 (jianshu.com)