一、介绍
(1)什么是模块与模块化?
将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程称之为模块化。
其中拆分出的每个文件就是一个模块,模块的内部数据是私有的,不过模块可以暴露内部数据,从而让其他模块可以使用。
2、什么是模块化项目?
整个项目由一个个单独的模块组成,这个项目就是一个模块化项目。
3、模块化的好处
- 防止命名冲突
- 高复用性
- 高可维护性
二、模块化初体验
目录结构
me.js文件
function tiemo(){
console.log('贴膜...');
}
module.exports = tiemo;
index.js文件
//导入模块
const tiemo = require('./me.js');
//调用函数
tiemo();
执行index.js文件,输出结果如下
贴膜...
三、模块的导入和导出
1、模块的导出
将对象赋值给module.exports或者exports,从而将模块中的值导出
第一种方式:使用module.exports = {属性名:导出的值};
//me.js文件
function write(){
console.log('贴膜...');
}
function print(){
console.log('绘画...');
}
let name = '张三';
module.exports = {
name: name,
write: write,
print: print
};
第二种方式:使用exports.属性名 = 导出的值;
//me.js文件
function write(){
console.log('贴膜...');
}
function print(){
console.log('绘画...');
}
let name = '张三';
exports.name = name;
exports.write = write;
exports.print = print;
exports和module.exports的关系:
在模块初始化时,exports和module.exports指向同一个空对象,初始化代码如下:
exports = module.exports = {};
在模块导出时,实际导出的值是module.exports
因此若定义一个新对象赋值给exports变量,则无法导出值,如下所示:
//me.js文件
function write(){
console.log('贴膜...');
}
function print(){
console.log('绘画...');
}
let userName = '张三';
exports = {
name: userName,
write: write,
print: print
};
在index.js文件中引入模块,由于没有给module.exports赋值,因此获取的是一个空对象
//index.js文件
//导入模块
const me = require('./me.js');
//打印导入的值
console.log(me);
输出结果是一个空对象
{}
2、模块的导入
(1)导入文件
在模块中使用require('模块名')导入模块,例:
const me = require('./me.js');
注意事项:
- 对于自己创建的模块,导入时路径建议写
相对路径,且不能省略./和../ js和json文件导入时可以不用写后缀,c/c++编写的node扩展文件也可以不写后缀- 如果导入其他类型的文件,会以
js文件进行处理
(2)导入文件夹(package.json)
如果导入的路径是个文件夹,则首先检测该文件夹下package.json文件中main属性对应的文件,如果存在则导入,如果文件不存在则报错。
例:目录结构
package.json
{
"main": "./app.js"
}
app.js
module.exports = "我是一个模块";
main.js
const m = require('./module');
console.log(m);
执行main.js,执行结果如下
我是一个模块
(3)导入文件夹(index.js)
如果main属性不存在,或者package.json不存在,则会尝试导入文件夹下的index.js和index.json,如果没有找到,则报错。
目录结构:
index.js
module.exports = '我是一个index.js文件';
main.js
const m = require('./module');
console.log(m);
执行main.js,执行结果如下
我是一个index.js文件
注:导入Node.js内置模块时,直接引用模块的名字即可,无需加./和../。
3、模块导入的过程
require()方法导入自定义模块的流程如下:
- 第一步:将相对路径转换为绝对路径,定位目标文件
- 第二步:缓存检测
- 第三步:读取目标文件代码
- 第四步:包裹一个函数并执行(立即执行函数),通过
arguments.callee.toString()查看立即执行函数。 - 第五步:缓存模块的值
- 第六步:返回
module.exports的值