【问题标题】:what should nodeJS/commonJS module.exports returnnodeJS/commonJS module.exports 应该返回什么
【发布时间】:2013-07-26 09:58:22
【问题描述】:

我知道我可以将module.exports 设置为对象或函数 (在某些情况下,函数会返回一个对象)。

我也知道使用 exportsmodule.exports 的区别和方法,因此无需对此发表评论。

我还了解到,返回的任何内容都会被缓存,并将在任何连续调用require 时返回。因此,如果我选择返回一个函数而不是一个对象,那么这可能意味着在每个 require 上都必须实际运行这个函数。

我想知道是否应该使用这两者中的哪一个有任何事实上的标准。或者,如果没有这样的标准——在决定我的模块是否应该返回一个对象、一个函数或更复杂的东西时,需要考虑哪些因素......

如果重要的话,我打算编写的模块有望用作 express 应用程序的一部分(也许 express/connect 模块有一个“本地事实标准”)。

【问题讨论】:

    标签: node.js express commonjs


    【解决方案1】:

    如果require'd 代码是独立的,并且不需要从父代码访问任何对象,我将export 一个对象。

    edit - 以上是我的首选方式。只有当我需要将东西传递到模块中时,我才执行以下操作,例如配置数据或我的数据库对象。我还没有找到一种更优雅的方式来让模块访问父级范围内的变量。

    所以要将对象从父级传递到模块中,我使用了一个函数:

    //parent.js
    var config = { DBname:'bar' };
    var child = require('./child.js')(config);
    
    //child.js
    module.exports = function(cfg){
      var innerchild = {};
      innerchild.blah = function(){
        console.log(cfg.DBname); // this is out of scope unless you pass it in
      }
      return innerchild;
    };
    

    【讨论】:

    • 说得好!这几乎是惯例。请注意他是如何将该函数用作生成具有特定于实例配置的对象的包装器。
    • 没错,当module.exports被调用时,我使用传入的cfg组装innerchild对象,然后返回该对象。我通常会有几个函数悬挂在innerchild 上,这些函数使用我传入的对象。
    • 总是使用函数方式是否没有意义,这样如果您在稍后阶段决定确实需要获取一些选项/设置,您就不会破坏 API 吗?并且更清楚地表明,每当您“需要”某些东西时,您就需要运行它。所以你没有 var m=require('pathToModule');m=require('pathToModule')(conf); 或者做类似m=require('pathToModule').init(conf);的事情会更好
    【解决方案2】:

    "这样如果我选择返回一个函数而不是一个对象,那么 可能这意味着在每一个需要它是必要的 实际运行这个函数。”

    返回一个单独的函数还是一个对象都没有关系。在这两种情况下都不会运行一个(或多个)函数。除非你明确地这样做。

    例如,考虑一个模块hello.js

    exports = function () { return 'Hello'; };
    

    您可以使用 require 来获取该功能:

    var hello = require('hello');
    

    如果要运行该函数,则需要显式调用它,如下所示:

    var hello = require('hello')();
    

    你写道你想确保你的函数只执行一次。直观地说,这可能会导致您将hello.js 编写如下:

    var hello = function () { return 'Hello'; };
    exports = hello();
    

    在这种情况下,您可以通过 require 存储来自 hello 的结果:

    var hello = require('hello');
    

    但是:如果你这样做the export system may cache your module。在这种情况下,您不会从 hello 获得新结果,而是从缓存值中获得。这可能是也可能不是您想要的。如果你想确保一个函数在每次需要时都被调用,你需要导出一个函数并在 require 之后调用它。

    【讨论】:

    • 我知道返回一个函数并不意味着调用 require 会运行它,但在这种情况下返回一个函数有什么意义呢?需要我的模块的代码很可能想要运行该函数(除非位于未执行的代码路径中)。
    • 请再读一遍我的Q。这是关于从要求返回的推荐/事实上的标准。
    • 关键是返回一个函数并立即执行它是确保函数每次被包含时都运行一次的唯一方法。查看编辑。
    • @jsalonen 缓存适用于每个节点会话 AFAIK。如果@epeleg 在运行他们的脚本时只有requires 一个模块;它应该只执行一次。如果您再次需要它,而无需重新启动脚本,那么缓存就会发挥作用
    • @Plato 你可能是对的。但是,从长远来看,我不会打赌。你忘了它,添加一些不错的额外缓存模块,突然一切顺利(╯°□°)╯︵┻━┻
    猜你喜欢
    • 2019-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 2017-12-12
    相关资源
    最近更新 更多