commonjs的本质

js 复制代码
this.a = 1;
exports.b = 2;

exports = {
  c: 3
}

module.exports = {
  d: 4,
};

exports.e = 5;

this.f = 6;

接下来理解 commonjs的本质,理解 commonjs的本质,什么题目都不难。

commonjs是一个模块化的标准,任何一个js文件,都是一个模块,每个模块有自己的导出结果。

我们要使用一个模块的时候,是不是要通过一个require函数,把模块路径传给他。

js 复制代码
const r = require('./2');
console.log(r);

那么这个函数一运行。这个函数一运行,是不是相当于是在运行这个模块。运行完成之后,这个函数还有一个返回结果。那么这个返回结果,拿到就是这个模块导出的结果。

要理解commonjs,就要理解require函数。它到底是怎么运行的,做了啥事,为什么这里的结果就是这里的导出结果。导出到底又是啥,这一切的疑团都在require函数的内部。那这个require函数是怎么写的呢,它这个是node在本地实现的。

写伪代码,逻辑大致相同。

js 复制代码
function require(modulePath) {
  // 1. 根据传递的模块路径,得到模块完整地绝对路径
  var moduleId = getModuleId(modulePath);
  
  // 2. 判断缓存
  if (cache[moduleId]) {
    return cache[moduleId];
  }
  
  // 3. 真正运行模块代码的辅助函数
  function _require(exports, require, module, __filename, __dirname) {
    // 目标模块的代码在这里
    // ...
  }
  
  // 4. 准备并运行辅助函数
  var module = {
    exports: {},
  };
  
  var exports = module.exports;
  
  // 得到模块文件的绝对路径
  var __filename = moduleId;
  // 得到模块所在目录的绝对路径
  var __filename = moduleId;
  // 得到模块所在目录的绝对路径
  var __dirname = getDirname(__filename);
  _require.call(exports, exports, require, module, __filelname, __dirname);
  
  // 5. 缓存 module.exports
  cache[moduleId] = module.exports;
  
  // 6. 返回 module.exports
  return module.exports;
}
js 复制代码
const r = require('./2');
console.log(r);

这就是整个 require 函数的 伪代码,看上去呢, 挺复杂。其实非常简单,

把整个的结果,放到一个函数里边。函数里边直接放置模块代码。

也就是说

js 复制代码
this.a = 1;
exports.b = 2;

exports = {
  c: 3
}

module.exports = {
  d: 4,
};

exports.e = 5;

this.f = 6;

这段代码一定是在函数里边,是函数一定要有一个arguments这么一个东西。全局里面没有,只有在函数里面才有。

真的能打印出来,说明啥,说明它在一个函数里边。

这个函数会给它传5个参数。

js 复制代码
function _require(exports, require, module, __filename, __dirname) {

}

再来打印一下arguments的长度。

js 复制代码
console.log(arguments.length);
  • exports
  • require
  • module
  • __filename
  • __dirname // 这个模块的目录的绝对路径

为什么在文件里面都可以直接使用,因为这5个它们都是参数。

有的用node的esmodule,然后这5个参数都不能用了。因为它不在一个函数环境里面了。

知识就是越深入越复杂,越深入越复杂,当深入到一定程度之后,反而变得更简单了。

反之,没有触碰到本质,那就是各种规则,要记exports表示啥意思,module.exports表达啥意思。要记各种各样的规则。

之后就是调用__require这个函数,调用的时候要准备好这5个参数。require参数就是require本身这个函数。

js 复制代码
var module = {
  exports: {},
}

var exports = module.exports;

module.exports 和 exports 是同一个东西。

__filename表示文件的绝对路径。

js 复制代码
var exports = module.exports; // 这就是模块的id

模块所在目录的绝对路径,通过内置模块就能够完成。

js 复制代码
// 得到模块文件的绝对路径
var __filename = moduleId;

// 得到模块所在目录
var __dirname = getDirname(__filename)

_require.call(exports, exports, require, module,  __filename, __dirname);

// 5. 缓存 module.exports
cache[moduleId] = module.exports;

// 6. 返回 module.exports
return module.exports;

this 和 exports 和 module.exports 是一个东西。一开始都指向同一个对象,都指向一个空对象。

yaml 复制代码
{ a: 1, b: 2, f: 6 }

exports
{ c: 3, e: 5 }

module.exports
{ d: 4 }

require函数最后返回的是module.exports。(从函数可以见得)。

相关推荐
Sailing4 小时前
5分钟搞定 DeepSeek API 配置:从配置到调用一步到位
前端·openai·ai编程
Pa2sw0rd丶4 小时前
如何在 React 中实现键盘快捷键管理器以提升用户体验
前端·react.js
非凡ghost4 小时前
ToDoList(开源待办事项列表) 中文绿色版
前端·javascript·后端
j七七4 小时前
5分钟搭微信自动回复机器人5分钟搭微信自动回复机器人
运维·服务器·开发语言·前端·python·微信
快起来别睡了4 小时前
TypeScript装饰器详解:像搭积木一样给代码加功能
前端·typescript
OpenTiny社区5 小时前
如何使用 TinyEditor 快速部署一个协同编辑器?
前端·vue.js
ttyyttemo5 小时前
加载图片,不同数据源,Compose实现
前端
Mike_jia5 小时前
Dumbterm:基于网页的终端革命!随时随地安全访问服务器的终极方案
前端
看今朝·5 小时前
【Dash框架】Dash回调函数中Output的属性详解
java·前端·dash