Js模块化
【成长期】原始的js模块化
// 使用立即执行函数 + var的方式
// 例如 有base.js 和 main.js两个文件
// 其中main.js需要调用base.js中的函数 可以这样写
/** base.js */
var baseModule = (function () {
var a = 1;
var b = 11;
var c = 22;
console.log(a, b, c);
function addA() {
a++;
}
return {
addA,
}
})()
/** main.js */
baseModule.addA();
【成熟期】CommonJs
// base.js
var a = 1;
var b = 2;
var c = 3;
module.exports = {
a, b, c
}
// main.js
const base = require('./base.js');
console.log(
base.a,
base.b,
base.c
)
/** 编译后实际执行的是以下的代码 */
// base.js
(
function (exports, require, module, __filename, __dirname) {
...
let count = 0;
const increase = () => ++count;
module.exports = {
increase,
count
}
return module.exports;
}
).call(thisValue, module.exports, require, module, __filename, __dirname)
// main.js
(
function (exports, require, module, __filename, __dirname) {
...
}
).call(thisValue, exports, require, module, __filename, __dirname)
● 缺点
○ 无法动态加载模块只支持同步加载模块
○ 因为commonJs是为了Nodejs设计的 没有异步问题不大
○ 服务器端同步加载模块的方案
面试题:
● module.exports跟export之间的关系
○ 两个指向的是同一个东西 module.exports = exports
○ module.exports可以支持只导出单个变量或者函数
● 如何避免循环引用
○ commonJs本身做了缓存 当require过某个文件时 它会将结果缓存下来
○ 下次使用就不用重新再走一遍
○ 可以重新设计该模块
AMD async module define
非同步加载模块
允许异步加载 define(id, [depends], callback); require([module], callback);
// 定义模块的方式
define(
'amdCountModule',
['depModule1', 'depModule2'],
(depModule1, depMOdule2) => {
return {
...
}
}
)
require(
['amdCountModule'],
amdCountModule => {
amdCountModule.xxx
...
}
)
// 如果再AMD中使用require的方式加载同步模块可以么?
define(require => {
...,
const depModule1 = require('depModule1');
const depModule2 = require('depModule2');
exports.xx = xx;
exports.cc = cc;
})
CMD
define(
function(require, exports, module) {
let depModule1 = require('depModule1');
deoModule1.xxx();
if (xxx) {
let depModule2 = require('depModule2');
}
}
)
UMD universal module define
…太复杂了
ESM ecmscript module
import xxx from '..';
import { xx } from '..';
export xxx;
export default {
...
}
// 在nodejs中使用esm
// 首先命名要改成 .mjs结尾
// node >= 13.2.0
// 如何支持异步加载
import('...'); // 返回的是一个promise