有没有什么理由使用IIFE来定义module.exports?

我的团队没有任何经验丰富的JS开发人员,但是我们正在Node中编写一个库,并从一个真正的JS开发人员那里得到了一个build议:“我们应该让js更模块化 – 不要污染全局命名空间并使其更具可读性对新来者“,并告诉我们要做到以下几点:

module.exports = (function(){ return { nameToExpose: functionToExpose ... }; })(); 

而不是

 module.exports.nameToExpose = functionToExpose; 

这有什么意义呢? 后者不做任何本地声明,这些声明将被IIFE所限定,即使这样做,它们也将是模块文件的本地模块,而不是整个程序的全局对象。

一些谷歌search和点击这个网站没有出现在这个特定问题上的任何答案,虽然还有许多其他解释我已阅读(以及上面的评论中概述)的IIFEs。 一些testing肯定揭示了后者实际上并没有functionToExpose放在全局名称空间中,尽pipe它的原名是logging在函数types本身中的。

几乎没有区别。 Node.js的整个概念,使用require ,具有模块等,是专门分离的关注点。 我会(谨慎地)说,如果你做得对,你不应该担心“污染”任何一种全球范围。 module.exports内的任何东西都在该模块中。

当你处理前端的东西的时候,这就是全局范围成为一个问题的时候,因为如果一个函数或者其他东西没有被作用域(即在一个IIFE或者其他function块中),它就可以访问全局window对象,以及其他一切都可以访问该函数。

一个真正的JS开发者

叫一个红旗的人

不要污染全球名字空间,并使新手更易读

如果你正确地模块化你的代码,这应该不是一个问题。 有一个IIFE的时间和地点,但我看不出为什么包装在一个已经在模块中的IIFE的所有东西都会以某种方式神奇地使代码“更模块化”,或者更易读为“新来者”简单地使用像devise的Node.js:

 module.exports = function() { ... } // whatever 

即使这样做,他们将是模块文件的本地,而不是整个程序require()的全局。

你是对的。 我可以把他所说的一切都拿走。 也许他知道一些特定的用例,他的方法在过去对他有帮助,所以我会特意问他,看看他说了什么。 除此之外,我觉得你在正确的轨道上。

有时候这样做的原因是因为如果你不这样做,那么module.exports对象所需的任何variables都必须被作用于整个文件。

考虑这两种方式。

  1. 没有IIFE。

     var foo = 'la' + 'la'; // some computed value // // ... lots of program code here ... // module.exports = { foo : foo, }; 
  2. 与IIFE。

     // // ... lots of program code here ... // module.exports = (function () { var foo = 'la' + 'la'; // some computed value return { foo : foo } }()); 

在第一个例子中,出现了两个问题。

  1. 你的variables(如foo )与它们用于从模块中导出值的地方相距甚远。 这可能会降低清晰度。 当然,你可以在程序代码之后声明一个variables,但是它仍然有相同的范围(并且variables被挂起 )。 另外,一般的最佳做法是首先声明所有的variables,而不这样做是一个折衷考虑。
  2. 程序代码可能会混淆你的variables,有意或无意,这使事情变得复杂,除非你需要(有时候你会这样做),这是不可取的。

第二个示例通过为该文件的该区域提供专用作用域来消除这些问题。 您仍然可以使用作用于整个文件的variables,但在不需要的情况下,您可以使用易于阅读和理解的variables。

通常我们为人类而不是机器编程。 这是前者优化的一个例子。

更新:

在JavaScript的现代版本中, const和let可能是这个模式要解决的问题的更好的解决scheme。 有了它们,你可以定义variables的方式,如果你犯了同样的错误IIFE试图保护你,将会抛出错误。

 // // ... lots of program code here ... // const foo = 'la' + 'la'; // some computed value module.exports = { foo : foo, }; 

在上面的例子中,如果程序代码使用foo ,由于Temporal Dead Zone ,它将会以ReferenceError崩溃,而不是像var那样接收undefined 。 这很好,因为现在你必须明确地将foo的声明移到代码中的一个更早的地方,如果它的使用是有意的,或者修复代码的话。