Javascript CommonJS - 模块在哪里?

Javascript CommonJS - where's the module?

所以我在个人项目中使用模块是出于通常的原因(命名空间保护和依赖性处理(需要)和 public API 定义(导出))。我编写了自己的 require() 方法并使用标准模块模式——即:

var myModule = (function() {
   var exports = {};

   function sayHello() {
      return "hi";
   }
   exports.sayHello = sayHello;

   return exports;
})();

所以我想在 CommonJS 标准上标准化我的东西(这是针对服务器端 JS,我的问题是不是关于 CommonJS 与其他模块标准的对比)。我读到的关于 CommonJS 的所有内容都说模块看起来像这样

function sayHello() {
   return "hi";
}
exports.sayHello = sayHello

就是这样!但这不是一个模块。一定是有什么东西把这个 包装成一个实际的模块! 我还没有找到一个讨论 CommonJS 模块的站点来说明它是如何变成一个实际的模块的。我错过了其他人似乎都知道的东西吗?

所以我的问题是:

包装是做什么的? ——也就是说,是什么把它变成了一个实际的模块?我假设是某种图书馆。

这个最终的、包装好的 CommonJS 模块是什么样子的?我想编写 CommonJS 标准的实现,但找不到任何关于最终模块应该是什么样子的文档。

"exports"变量是否在全局范围内?如果不是,如果没有在模块代码的主体中显式声明,那么向模块提供导出对象的是什么?谁在做 - 模块的调用者?

该死。自己写的时候好像很简单。现在它看起来像魔术。 link 一些全面的文档会很棒。

注意:我对node.js了解很少并且不打算在这个项目中使用它,所以如果您回答,请不要用 node.js-speak.

回答

What is doing the wrapping?

节点是。它可以访问文件系统,因此它缓存所有需要的文件中的代码,并将其传送到需要它的命名空间。

What does this final, wrapped, CommonJS module look like?

包装模块的实际代码可能在 module.js 中,这是 Node 安装的 lib 文件夹中的核心文件。

Is the "exports" variable in the global scope?

exports 是文件中 module 对象的 属性。 module 是该文件中的全局范围。 exports 属性 是模块返回给需要它的代码的内容。

要记住的关键是 CommonJS 精神是内置于 Node 的核心模块化代码中的。 V8 中没有神奇的实现来规定 module.exports 是 'thing'。当实现 ES6 模块成为常态时,这一切可能都会改变。

您可能会发现阅读 this 很有用。

您可能会发现放弃重写 require() 更有用。 :-)

我希望 node.js 文档能够回答您的所有问题。

所以,根据 node.js documentation

在执行模块代码之前,Node.js 将使用如下所示的函数包装器对其进行包装:

(function(exports, require, module, __filename, __dirname) {
  // Module code actually lives in here
});

通过这样做,Node.js 实现了一些目标:

  • 它将 top-level 变量(用 varconstlet 定义)限定在模块范围内而不是全局对象。
  • 它有助于提供一些实际上特定于模块的 global-looking 变量,例如:
    • 实现者可以用来从模块导出值的 moduleexports 对象。
    • 便利变量 __filename__dirname,包含模块的绝对文件名和目录路径。