简述
模块是对携带某些功能的代码的封装,有利于代码的解耦和复用,数据和实现存在于模块作用域,向外暴露一些变量或函数; 目前前端模块化相关的规范有AMD、CMD、CommonJS、ESModule
AMD-require.js和CMD-sea.js
AMD-require.js
AMD是RequireJS在推广过程中对模块定义的规范 AMD异步加载模块,用define定义模块、require引入模块、return暴露模块,用于浏览器环境
定义模块:define
// 定义没有依赖的模块
define(function(){
return 模块
})
// 定义有依赖的模板
define(['module1', 'module2'], function(m1, m2){
return 模板
})
引入模块:require
require(['module1', 'module2'], function(m1, m2) {
使用m1/m2
})
定义和暴露模块:return
define(['module1'], function(m1) {
let name = 'pdx'
function showName() {
console.log('showName', name)
}
// 暴露模块
return { showName }
})
CMD-sea.js
CMD是SeaJS在推广过程中对模块定义的规范 CMD异步加载模块,用define定义模块、require引入模块、export暴露模块,用于浏览器环境,模块在使用时才会加载执行
引入、定义和暴露模块:
define(function(require, exports, module) {
const module1 = require('./module1')
const showName = function () {
console.log('name: pdx')
}
export.showName = showName
})
CMD与AMD区别
1.定义模块处理依赖方式不同,AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块;CMD推崇就近依赖,只有在用到某个模块的时候再去加载
2.都是异步加载模块,但是AMD加载完模块后立刻执行,而CMD是等所有依赖都加载完后才执行(这是AMD用户体验好、CMD性能好的原因)
CommonJS
Node就是采用CommonJS模块规范,不过目前还是盛行ESM,Node很多源码也是改成ESM
CommonJS模块特点: 1.所有代码运行在模块作用域内,不会污染全局变量
2.模块是同步加载
3.模块首次执行后会缓存,再次加载获取的是缓存结果
4.CommonJS输出是值的拷贝,也就是说require返回的值是被输出的值的拷贝,模块内部的变化也不会影响这个值(加载机制)
// a.js
var num = 1
function reduceNum() {
num++;
}
module.exports = {
num: num,
reduceNum: reduceNum
};
// main.js
var num = require('./a.js').num;
var reduceNum = require('./a.js').reduceNum;
console.log(num); // 1
reduceNum()
console.log(num); // 1
引入模块:require
var dayjs = require('day.js')
暴露模块:export
var name = 'pdx'
module.export.name = name
// 或者
export.name = name
ESModule
ES6 Module的设计思想是尽量的静态化(在此简称ESM或ESModule),使得编译时就能去确定模块的依赖关系,以及输入和输出的变量 CommonJS和AMD都是运行时才确定依赖关系。比如CommonJS模块就是对象,输入时必须查找对象属性。
import引入、export暴露
var add = function (val) {
return val++
}
export { add }
import { add } from './add.js'
var age = 1;
add(age)
console.log('age:', age) // 2
使用import命令时,需要引入正确的变量名或函数名;如果使用export default,则import时可以自定义名字 加载机制:动态引用
// a.js
var num = 1
function reduceNum() {
num++;
}
exports {
num,
reduceNum
};
// main.js
import { num, reduceNum } from './a.js'
console.log(num); // 1
reduceNum()
console.log(num); // 2
ESModule与CommonJS区别
1.CommonJS模块输出的是一个值的拷贝,而ESM模块输出的是值的引用
2.CommonJS模块时运行时加载,而ESM模块是编译时输出接口