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

Rya*_*ich 17 javascript node.js iife

我的团队没有任何经验丰富的JS开发人员,但是我们正在Node编写一个库,并得到了一个真正的JS开发人员的建议:"我们应该使js更加模块化 - 不要污染全局命名空间并使其更具可读性对新人说,"并告诉我们做以下事情:

module.exports = (function(){
      return {
         nameToExpose: functionToExpose
         ...
    };
})();
Run Code Online (Sandbox Code Playgroud)

而不是

module.exports.nameToExpose = functionToExpose;
Run Code Online (Sandbox Code Playgroud)

有什么意义,如果有的话?后者不会制作任何本地声明,这些声明将由IIFE确定,即使它确实如此,它们将是模块文件的本地声明,而不是整个程序的全局声明require().

关于这个网站的一些谷歌搜索和挖掘并没有找到关于这个特定问题的任何答案,尽管我已经读过很多其他IIFE的解释(并且在上面的评论中总结了这些解释).一些测试肯定会发现后者实际上没有放入functionToExpose全局命名空间,尽管它的原始名称记录在函数类型本身中.

Jos*_*eam 14

几乎没什么区别.Node.js的整个想法,使用require,具有模块等,专门用于区分问题.我(小心地)说,如果你做得对,你不应该担心"污染"任何类型的全球范围.module.exports生活在该模块中的任何东西.

当你处理前端的东西时,那就是当全局范围成为一个问题时,因为如果一个函数或任何不是作用域的(即在IIFE或其他功能块中),它可以访问全局window对象,其他所有内容都可以访问该功能.

一个真正的JS开发人员

打电话给那个红旗的人.

不要污染全局命名空间并使其对新手更具可读性

如果您正确地模块化您的代码,那不应该是一个问题.IIFE有一个时间和地点,但我认为没有理由将IIW中的所有内容包装在一个模块中,它会以某种方式神奇地使代码"更模块化"或者对"新来者"更具可读性而不是简单地使用像它设计的Node.js:

module.exports = function() { ... } // whatever
Run Code Online (Sandbox Code Playgroud)

即使它确实如此,它们将是模块文件的本地文件,而不是整个程序的全局require().

你是对的.我不顾一切地说他的话.也许他知道一些具体的用例,他的方法在过去对他很有帮助,所以我会特意问他,看看他说的是什么.除此之外,我觉得你走在正确的轨道上.


Set*_*day 9

有时可能会这样做的原因是因为如果不这样做,那么module.exports对象所需的任何变量都必须限定为整个文件.

考虑这两种方式.

  1. 没有IIFE.

    var foo = 'la' + 'la';  // some computed value
    
    //
    // ... lots of program code here ...
    //
    
    module.exports = {
        foo : foo,
    };
    
    Run Code Online (Sandbox Code Playgroud)
  2. 有了IIFE.

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

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

  1. 您的变量(如foo)创建的距离远离用于从模块中导出值的位置.这可能会降低清晰度.当然,您可以在程序代码之后声明一个变量,但它仍然具有相同的范围(并且vars被提升).另外,一般的最佳做法是预先声明所有变量,而不是这样做是需要考虑的权衡.
  2. 程序代码可能会有意或无意地弄乱您的变量,这会使事情变得复杂并且除非您需要(有时您这样做),否则是不受欢迎的.

第二个示例通过为文件的该区域设置专用范围来消除这些问题.您仍然可以使用作用于整个文件的变量,但是在您不需要的变量的情况下,您可以使用更易于阅读和理解的变量.

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

更新:

在现代版本的JavaScript中,constlet可能是解决此模式旨在解决的问题的更好解决方案.有了它们,你可以定义变量,如果你犯了同样的错误,IIFE试图保护你,就会抛出错误.

//
// ... lots of program code here ...
//

const foo = 'la' + 'la';  // some computed value

module.exports = {
    foo : foo,
};
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,如果程序代码使用foo,它会ReferenceError因为时间死区而崩溃,而不是undefined作为一个遗嘱接收var.这很好,因为foo如果它的使用是有意的,或者以其他方式修复代码,现在必须显式地将声明移动到代码中的较早位置.