一、什么是模块化
- 将一个复杂的程序文件依据一定规则拆分多个文件的过程称为 模块化 。
- 其中拆分出来的 每个文件 就是一个模块化,模块内部的数据是私有的,不过模块可以暴露内部数据以供其他模块使用。
- node.js实现了CommonJS模块化规范。module.exports、exports 以及 require 都是CommonJS模块化规范内容
二、模块化的使用
1.暴露数据
- module.exports = value
- exports.name = value
- 这两种用法不能混用
foo.js
const circle = require('./circle.js');
//第一种
console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`);
//第二种
// circle.test();
// circle.test2();
circle.js
//变量 PI 是 circle.js 私有的。
const {
PI
} = Math;
function test() {
console.log('test1');
}
function test2() {
console.log('test2');
}
//暴露数据
//第一种 独立变量
// module.exports.f = ... 可以被更简洁地写成 exports.f = ...。
exports.area = (r) => PI * r ** 2;
exports.circumference = (r) => 2 * PI * r;
//第二种 属性
// module.exports ={
// test,
// test2
// }
注意:
- module.exports可以暴露任意数据
- 不能使用 exports = value的形式暴露数据,模块内部module与exports的隐式关系 exports = module.exports = {}
三、导入模块
在模块中使用require传入文件路径即可引入
- 若导入的是文件,
- 对于自己创建的模块,导入模块要写相对路径,不能省略 ./ 和 ../
- js 和 json 文件导入时可省略后缀
- 若同时存在文件名相同的文件,则先查看是否存在后缀为js的文件,有则导入;若不存在,再查看是否存在后缀为 json 的文件,有则导入;若导入的是其他类型的文件,也会以 js 文件进行处理。
- 若导入的是文件夹,
- 首先会检测该文件下的package.json文件对应的main 属性对应的文件,有则导入,不存在则会报错。
- 若main属性不存在,或package.json不存在,则会尝试导入文件夹下的inde.js文件或index.json文件,有则导入,不存在则会报错。
- 导入node.js内置模块,直接导入即可,如fs模块。
四、导入自定义模块基本流程
- 将相对路径转为绝对路径,定义目标文件
- 缓存检测
- 读取目标文件代码
- 包裹一个函数并执行。通过 arguments.callee.toString() 查看函数体
- 缓存模块的值
- 返回 module.exports 的值
function require(file) {
//将相对路径转成绝对路径,定位目标文件
let absolutePath = path.resolve(__dirname, file)
//缓存检测
if (caches[absolutePath]) {
return caches[absolutePath]
}
//读取文件代码
let code = fs.readFileSync(absolutePath).toString();
let exports ={};
let module = module.exports = {};
//包裹一个函数执行
(function (exports, require, module, __filename, __dirname) {
const test = {
name: '测试'
}
module.exports = test;
//函数代码体
console.log(arguments.callee.toString());
})(exports, require, module, __filename, __dirname)
//5.缓存结果 模块对象
caches[absolutePath] = module.exports;
}