在JS中,我们都是直接使用require去直接引入一个模块使用
const result = require("./myModule.js");
console.log(result);
为什么可以直接使用require函数?且能得到
myModule.js中导出的结果?
我们来举个例子:
以下是我要引入的模块文件myModule.js
module.exports = {
a: 1,
b: 2
};
console.log(this === exports); // true
以下是我使用模块内容的文件index.js
const result = require("./myModule.js");
console.log(result); // {a:1,b:2}
在myModule.js的 this指向的是 exports
实际上,每个JavaScript文件可以作为一个模块使用,是因为它们都被放到一个函数中处理过。下面我们就用伪代码来说说:
const requireCache = {};
function require(modulePath) {
// 1. 将 modulePath转为绝对路径
const absPath = path.resolve(__dirname, modulePath);
// 2. 判断是否有该模块的缓存,有则返回模块内容
if (requireCache[absPath]) {
return requireCache[absPath];
}
// 3. 读取模块文件内容
requireCache[absPath] = '模块内容'
// 4. 包裹到一个函数中
function _temp(module, exports, require) {
module.exports = {
a: 1,
b: 2,
};
console.log(this === exports);
}
// 5. 创建 module 对象
const module = { exports: {} };
const exports = module.exports;
// 6. 绑定this
_temp.call(exports, module, exports, require);
// 7. 返回模块内容
return module.exports;
}
总结:
使用CommonJS的require函数时,会将整个模块内容丢到一个函数中做处理,然后创建module对象,将这个对象绑定为函数中的this,最后返回模块内容。
PS:
实际require函数的实现肯定是更复杂的,今天学习到这儿啦。