【问题标题】:Why we need to pass module.exports as a parameter since we are already passing module as a parameter?为什么我们需要将 module.exports 作为参数传递,因为我们已经将模块作为参数传递了?
【发布时间】:2018-01-08 10:45:31
【问题描述】:

我一直在浏览一些关于 Node.js 的在线教程。我的理解是,在使用require(./file-path) 函数时,节点获取该文件的内容并包装在立即调用函数中

(function(exports, require, module, __filename, __dirname) {
  // content 
}())

我了解exportsmodule.exports 之间的区别。这就是我在互联网上搜索上述问题时所能看到的全部内容。但我的问题是,为什么我们需要将module.exportsmodule 传递给包装IIFE?我们可以单独传递模块,然后从中获取module.exports。这样做有什么好处吗?通常当我们将对象传递给函数时,我们不必额外传递object.property

【问题讨论】:

    标签: javascript node.js module require


    【解决方案1】:

    最初只有exportsrequire。 后来,module 以向后兼容的方式添加,以允许(除其他外)完全覆盖导出对象。

    【讨论】:

    • 让我看看能不能找到零钱。我认为它在 v0.6 左右。
    • 后来他们添加模块时,为什么不删除 module.exports 呢?他们无论如何都可以从模块对象中获取它。
    • @MELWINVINCENT 因为这会破坏使用新平台的旧模块和使用旧平台的新模块。
    【解决方案2】:

    答案是:历史原因。

    你说得对,我们可以只有 moduleexports 不需要,但它仍然存在以实现向后兼容性。

    过去几乎每个补丁版本都会更改模块包装器。

    在 Node 0.1.11 中,模块包装器是:

    var wrapper = "function (__filename) { "+
                  "  var onLoad; "+
                  "  var onExit; "+
                  "  var exports = this; "+
                  content+
                  "\n"+
                  "  this.__onLoad = onLoad;\n"+
                  "  this.__onExit = onExit;\n"+
                  "};\n";
    

    见:https://github.com/nodejs/node/blob/v0.1.11/src/node.js#L167#L177

    如您所见,exports 与调用包装函数时使用的this 相同。你不能用一个新对象交换它,你甚至不能给它添加一些保留的键——例如。您无法安全地导出名为 __onExit 的属性。

    然后在 0.1.12 中是:

    var wrapper = "function (__filename, exports) { " + content + "\n};";
    

    见:https://github.com/nodejs/node/blob/v0.1.12/src/node.js#L243-L245

    这里的exports 是作为参数之一提供的对象,但您不能将其与新对象交换,您只能从获得的对象中添加或删除属性。

    那么0.1.13是第一个有这个的,即requireinclude

    var wrapper = "function (__filename, exports, require, include) { " + content + "\n};";
    

    见:https://github.com/nodejs/node/blob/v0.1.13/src/node.js#L225-L227

    然后 0.1.14 是第一个在包装器中包含 __module(带下划线)的版本(并且删除了 include):

    var wrapper = "var __wrap__ = function (__module, __filename, exports, require) { " 
                + content 
                + "\n}; __wrap__;";
    

    见:https://github.com/nodejs/node/blob/v0.1.14/src/node.js#L280-L284

    0.1.16 是第一个在包装器中有 module 参数(没有下划线)的:

    var wrapper = "var __wrap__ = function (exports, require, module, __filename) { " 
                + content 
                + "\n}; __wrap__;";
    

    见:https://github.com/nodejs/node/blob/v0.1.16/src/node.js#L444-L448

    在那之后它被更改了很多次,但这是 module 引入的时间,使得 exports 不再需要,但仍然是一个有用的快捷方式,允许您使用:

    exports.a = 1;
    exports.b = 2;
    exports.c = 3;
    

    代替:

    module.exports.a = 1;
    module.exports.b = 2;
    module.exports.c = 3;
    

    虽然在实践中,如果没有exports,那么通常会这样写:

    const exports = module.exports;
    exports.a = 1;
    exports.b = 2;
    exports.c = 3;
    

    或更可能:

    module.exports = {
      a: 1,
      b: 2,
      c: 3,
    };
    

    或者,在静态分析工具中进行一些检查:

    const a = 1;
    const b = 2;
    const c = 3;
    module.exports = { a, b, c };
    

    有很多方法可以做到,这是一种非常灵活的机制。

    【讨论】:

    • 打败我。比我记忆中的要早。
    猜你喜欢
    • 1970-01-01
    • 2014-03-12
    • 2016-05-04
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2019-10-17
    • 1970-01-01
    相关资源
    最近更新 更多