构建一个JavaScript库,为什么要这样使用IIFE?

17
我注意到很多库都使用下面的样式来定义它们的库。我还注意到第一个自调用函数与Require.js或AMD系统有关,它们总是把工厂作为参数,我会更深入地了解Require.js,一直在研究Browserify。
为什么主要代码被传递到第一个自调用函数结尾的括号中?这是一个闭包,还是仅被认为是匿名函数?我将深入研究两个问题。这样做有什么好处?看起来在闭包内,作者传递了一个字符串、一个this和一个回调函数。
这样做会给我的库提供一个干净安全的方式来将主对象全局化吗?下面的示例Please
(function( globalName, root, factory ) {
    if ( typeof define === 'function' && define.amd ) {
        define( [], factory );
    }
    else if ( typeof exports === 'object' ) {
        module.exports = factory();
    }
    else{
        root[globalName] = factory();
    }
}('Please', this, function(){

我正在努力深入学习JavaScript,并创建我自己的小型MVC架构,我不想听到我很傻或者这已经被做过了,我想挑战自己并学习。

如果有任何创建JavaScript库或更好的MVC库的优秀资源,我会很高兴知道。

2个回答

15
这个代码模式被称为通用模块定义(UMD)。它允许您在不同的环境中使用JavaScript库。它提供了三种定义模块的方式:
  1. 异步模块定义(AMD),由RequireJSDojo Toolkit实现。

    define( [], factory );

  2. CommonJS — NodeJS模块。

    module.exports = factory();

  3. 将模块分配给全局对象,例如浏览器中的window

    root[globalName] = factory();

IIFE有三个参数:globalNamerootfactory
  • globalName是您的模块名称。它仅适用于第三种定义模块的方式,即将您的模块对象分配给全局变量。例如,如果您将此参数设置为"myAwesomeModule"并在浏览器中使用代码(没有AMD),则可以使用myAwesomeModule变量访问您的模块。
  • root是全局对象的名称。显然,它也仅适用于第三种定义模块的方式。通常将this作为此参数传递,因为this是浏览器中window的引用。但是,在严格模式下不起作用。如果您希望您的代码在严格模式下工作,则可以将this替换为typeof window!==“undefined”?window:undefined
  • 最后,factory是一个匿名函数,应该返回您的模块作为对象。

另请参阅:


11

这是一个通用模块定义(UMD)的示例。它是一种技术,可使JS模块与三种流行的JS模块规范兼容:

  1. 异步模块定义(AMD,由Require.js使用)

    define('name', [ /* dependencies */ ], factory);
    
  2. CommonJS(Node.js生态系统)

  3. module.exports = object;
    
  4. 全球出口(例如,在浏览器中的 window 上)

  5. global['name'] = object;
    

UMD通过将一个负责创建要导出的对象的工厂函数包装为参数传递给一个立即执行函数表达式(IIFE),如您所粘贴的片段中所示。 IIFE负责检测模块环境,并以适当的方式导出工厂创建的对象。 模式如下:

(function (name, root, factory) {
   // detect the module environment and
   // export the result of factory()
})('name', this, function () {
   // module code
   // return the object to be exported
});

许多转译器和构建工具自动生成此包装器。


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