为什么可以在JS中直接使用require函数?

103 阅读1分钟

在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.jsthis指向的是 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;
}

总结:

使用CommonJSrequire函数时,会将整个模块内容丢到一个函数中做处理,然后创建module对象,将这个对象绑定为函数中的this,最后返回模块内容。

PS:

实际require函数的实现肯定是更复杂的,今天学习到这儿啦。