当执行一个模块或使用require时,会将模块放置在一个函数环境中
假如有两个模块:myModule.js 和 index.js, index.js中导入myModule.js。 代码如下:
myModule.js
console.log("当前模块路径:", __dirname);
console.log("当前模块文件:", __filename);
this.m = 5;
exports.c = 3;
module.exports = {
a: 1,
b: 2
}
index.js
const result = require("./myModule");
console.log(result)
执行结果为:
假如说myModule.js的代码为:
console.log("当前模块路径:", __dirname);
console.log("当前模块文件:", __filename);
this.m = 5;
exports.c = 3;
module.exports.a = 1
module.exports.a = 2
执行结果为:
这是为什么呢? index.js 执行 require("./myModyle")时,会执行以下代码(伪代码):
function require(modulePath) {
//1. 将modulePath转换为绝对路径:**:\***\****\node的模块化细节\myModule.js
//2. 判断是否该模块已有缓存
if(require.cache["**:\***\****\node的模块化细节\myModule.js"]){
// 如果有缓存,返回模块的运行结果
return require.cache["**:\***\****\node的模块化细节\myModule.js"].result;
}
// 如果没有缓存
//3. 读取文件内容
//4. 包裹到一个函数中
function __temp(module, exports, require, __dirname, __filename) {
console.log("当前模块路径:", __dirname);
console.log("当前模块文件:", __filename);
exports.c = 3;
module.exports = {
a: 1,
b: 2
};
this.m = 5;
}
//5. 创建module对象
module.exports = {};
const exports = module.exports;
__temp.call(module.exports, module, exports, require, module.path, module.filename)
// 运行函数,最终返回的是module.exports
return module.exports;
}
require.cache = {};
我们可以看到, myModule.js模块代码是放在一个函数中执行的,函数会给一些参数:module, exports,require, __dirname, __filename
然后调用函数时,将this指向了module.exports。同时需要注意,创建module对象时是这样的
//5. 创建module对象
module.exports = {};
const exports = module.exports;
所以最初,module.exports, exports, this都是指向的同一地址。但是执行函数后,返回的是module.exports。因此第一次执行结果返回的是:{a:1, b:2} 是因为执行到代码:
module.exports = {
a: 1,
b: 2
}
时,module.exports 被重新赋值了,而exports和this还是指向的原来的地址,所以只返回了:{a:1, b:2}。第二次返回结果是:{m:5, c:3, a:1, b:2}是因为exports,this, module.exports指向的是同一地址。
综上,myModule模块中的代码是放在函数中执行的,函数给一些参数:module, exports,require, __dirname, __filename,所以可以打印__dirname和__filename,同时需要注意调用函数时this的指向。
建议在平时要不全部用module.exports,要么全部用exports