一、模块化
- 将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程称之为模块化。其中拆分出每个文件就是一个模块,模块的内部数据是私有的,不过模块可以暴露内部数据以便其他模块使用。
- 编码时是按照模块一个一个编码的,整个项目就是一个模块化的项目。
- 好处:防止命名冲突;高复用;高维护。
二、模块化的暴露数据
模块化暴露数据的方式有两种
- module.exports = value
- exports.name = value 注意:
- module.exports可以暴露任意数据
- 不能使用exports = value的形式暴露数据,模块内部module与exports的隐式关系exports=module.exports={}
- require返回的是目标模块的module.exports的值而不是exports的值。
1、模块暴露一个数据
// 声明一个函数
function minFun(){
console.log("Min函数");
}
// 导出数据(模块暴露数据)
module.exports = minFun
// 导出模块 require('./min.js')指定的module.exports部分
const min = require('./min.js')
// 调用函数
min()
2、模块暴露多个数据
// 声明一个函数
function minFun() {
console.log("Min函数1");
}
function minFun2() {
console.log("Min函数2");
}
function minFun3() {
console.log("Min函数3");
}
// 导出数据
module.exports = { minFun, minFun2, minFun3 };
// 导出模块 require('./min.js')指定的module.exports部分
const min = require('./min.js')
// 调用函数
min.minFun()
min.minFun2()
min.minFun3()
3、第二种暴露数据的写法
module.exports是属性 export是独立的变量
// 声明一个函数
function minFun() {
console.log("Min函数1");
}
// 导出数据
exports.minFun = minFun;
exports.name='yt'
exports.arr=[1,2,3]
// 导出模块 require('./min.js')指定的module.exports部分
const min = require('./min.js')
// 调用函数
min.minFun()
console.log(min.name);
console.log(min.arr);
三、导入文件模块
在模块中使用require传入文件路径即可引入文件
const min = require('./min.js')
// 导入json文件
const json = require('./info')
console.log(json);//{ name: 'yt', age: 22 }
//导入其他文件
//注意文件夹要按"module.exports='1233444'"格式导入
const otherText = require('./text.abc')
console.log(otherText);
reuire使用的一些注意事项
- 对于自己创建的模块,导入时的路径建议写相对路径,且不能省略./和../
- js和json文件导入时可以不用写后缀,c/c++编写的node扩展文件也可以不写后缀,但是一般用不到
- 如果导入其他类型的文件,会以js文件进行处理
- 如果导入的路径是个文件夹,则会首先检测该文件夹下package.json文件中mian属性对应的文件,如果存在则导入,反之如果文件不存在会报错。如果mian属性不存在,或者package.json不存在,则会尝试导入文件夹下的index.js和index.json,如果还是没找到,就会报错
- 导入node.js内置模块时,直接require模块的名字即可,无需加./和../
- module.exports、exports以及require这些都是CommonJS模块化规范中的内容,而Node.js实现了CommonJS模块化规范
四、导入模块的基本流程
require导入自定义模块的基本流程
- 将相对路径转为绝对路径,定位目标文件
- 缓存检测
- 读取目标文件代码
- 包裹为一个函数并执行(自执行函数)。通过arguments.callee.toString()查看自执行函数
- 缓存模块的值
- 返回module.exports的值
const people = {
name :"yt",
getName:()=>{
console.log(name);
}
}
module.exports = people
console.log(arguments.callee.toString());
/**
* 伪代码
*/
function require(file) {
// 1、把相对路径转为绝对路径,定位目标文件
let absolutePath = path.resolve(__dirname, file);
// 2、缓存检测(用于检测之前是否有加载过这个文件)
if (caches[absolutePath]) {
return caches[absolutePath];
}
// 3、读取文件的代码
let code = fs.readFileSync(absolutePath).toString();
let module = {}
let exports = module.exports = {}
// 4、包裹为一个函数并执行
(function (exports, require, module, __filename, __dirname) {
const people = {
name: "yt",
getName: () => {
console.log(name);
},
};
module.exports = people;
console.log(arguments.callee.toString());
})(exports, require, module, __filename, __dirname);
// 缓存结果
caches[absolutePath] = module.exports;
}
const m = require("./me.js");
五、CommonJS模块化规范
module.exports、exports以及require这些都是CommonJS模块化规范中的内容。而Node.js是实现了CommonJS模块化规范,二者关系有点像JavaScript与ECMAScript。