在Node.js中有不同的module.exports模式

4
假设我们正在使用node.js和express(Note应用程序)创建简单的应用程序。我们希望组织我们的代码并将所有控制器放在单独的文件夹中。因此,我们创建一个文件夹并在其中创建index.js。然后我们将我们的控制器js文件添加到该文件夹中。接下来,在index.js的主入口点中初始化所有控制器,然后在server.js中使用require访问我们的控制器。(我不喜欢大而笨重、杂乱无章的server.js文件!)
所有这些示例代码都可以正常工作,但我无法理解这些代码块之间的区别。
1.
module.exports.init = function(app){
    console.log("notes controller init.");
};

2.

function init(app){
    console.log("notes controller init.");
};
module.exports.init = init;

3.

(function (notesController){
    notesController.init = function(app){
        console.log("notes controller init.");
    };
})(module.exports);

4.

module.exports = {
    init: function(app){
        console.log("notes controller init.");
        }
    }

这些 JavaScript 函数在性能或加载方面是否有差异,或者只是编码风格的多样性?

谢谢。

附言:

我是一名后端 C# 开发人员,曾经讨厌 JavaScript!但我正在尝试理解这种语言的本质,因为要使用 Node.js。 我在 Google 上搜索了很多有关 JavaScript 中的模块、导出和原型等内容,但找不到答案。


性能确实有差异,但由于其微不足道,因此您无法测量它。 - zerkms
@zerkms 哪一个更好? - Navid
1
你忘记了 module.exports = { init: function(app){console.log("notes controller init.");}} - aebabis
从哪个角度来看,“更好”? - zerkms
@zerkms 程序员之间总是存在一些契约或惯例。比如在C#或Java代码文件中公共和私有方法的顺序。哪一个更受社区认可?我们能否说其中一个因某种原因不好? - Navid
@acbabis 谢谢,我已经更新了问题并添加了第四个选项。 - Navid
1个回答

4
选项#1声明一个未命名的函数,并直接分配给module.exports.init
选项#2创建了一个本地命名的函数init,然后将其分配给module.exports.init。对于module.exports.init来说,在#1和#2之间没有任何功能上的区别。#2创建了本地符号init,可以用作执行该函数的本地快捷方式。但是,使用任何四个选项执行module.exports.init()的结果完全相同。
选项#3创建了一个本地IIFE函数作用域,允许您拥有私有变量,您的init函数可以使用这些变量,从一次方法调用到下一次会保留这些私有变量,并且在您的模块内部也是私有的(您的模块的其他部分甚至无法访问它们)。您不声明其中任何私有变量,但是可以这样做。除此之外,所有三个选项都将分配相同的函数引用给module.exports.init,因此module.exports.init的执行与前两个选项没有任何区别。
选项#4定义了一个新的export.modules对象,然后静态声明其中一个方法。这可以是一种有用且紧凑的方法,用于定义大量所有导出的方法(这是一种常见的设计模式),但是当仅声明单个导出方法时,我个人不会使用它,因为选项#1更加简单。
这些选项之间的任何性能差异仅在初始化期间出现,可能非常小,难以衡量或者并不重要。
哪个选项最好完全取决于观点。我个人偏爱遵循良好编码实践并完成任务的最简单的解决方案。对我来说,这将是选项#1,因为似乎没有理由在本地定义init(选项#2)或没有任何目的地使用IIFE进行私有符号定义(选项#3)。
如果我要声明多个导出方法,则通常会自己使用选项#4,因为它是最紧凑的语法。

不仅在这个例子中没有使用IEFE,而且考虑到每个模块已经有了自己的模块作用域,它似乎特别多余。 - Bergi
1
@Bergi - 是的,IIFE 提供了对你自己模块中其他部分的隐私保护,因为通过模块的函数作用域已经有了来自外部世界的隐私保护。 - jfriend00
@Navid - 在新添加的选项#4上添加了注释。 - jfriend00
@jfriend00 感谢您详细和富有信息量的回答! - Navid
1
@Navid - 你知道在StackOverflow上,如果你得到了问题的答案,你应该勾选最佳答案旁边的绿色复选标记吗?这告诉社区你的问题已经得到了解答,并为你赢得了一些声望分数。 - jfriend00
@jfriend00,抱歉。昨晚在发送最新评论之前我已经检查了绿色勾号!可能是由于我的ISP和/或伊朗的网络问题。无论如何,再次感谢。 - Navid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接