构建一个 JavaScript 库,为啥要以这种方式使用 IIFE?

Posted

技术标签:

【中文标题】构建一个 JavaScript 库,为啥要以这种方式使用 IIFE?【英文标题】:Building a JavaScript library, why use an IIFE this way?构建一个 JavaScript 库,为什么要以这种方式使用 IIFE? 【发布时间】:2016-04-24 07:40:09 【问题描述】:

我注意到很多库使用下面的这种样式来定义他们的库。我还注意到第一个自调用函数与 Require.js 或 AMD 系统有关,它们总是将工厂作为参数,我将更多地研究 Require.js,一直到 Browserify。

为什么将主要代码传递到括号内的第一个自调用函数的末尾,这是一个闭包,还是只是一个匿名函数,我将深入研究两者。这样做有什么好处?看起来作者在闭包内部传递了stringthiscallback

这会给我的库一个干净安全的方式来全球化下面这个例子中的主要对象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 库的资源,我很想知道。

【问题讨论】:

【参考方案1】:

此代码模式称为Universal Module Definition (UMD)。它允许您使您的 JavaScript 库在不同的环境中可用。它提供了三种定义模块的方式:

    Asynchronous Module Definition (AMD),由RequireJS 和Dojo Toolkit 实现。

    define( [], factory );

    CommonJS — NodeJS 模块。

    module.exports = factory();

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

    root[globalName] = factory();

IIFE 具有三个参数:globalNamerootfactory

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

另见:

What is the (function() )() construct in JavaScript? What Is AMD, CommonJS, and UMD?

【讨论】:

【参考方案2】:

这是Universal Module Definition (UMD) 的示例。这是一种使 JS 模块与三种流行的 JS 模块规范兼容的技术:

    Asynchronous Module Definition(AMD,Require.js 使用)

    define('name', [ /* dependencies */ ], factory);
    

    CommonJS(Node.js 生态系统)

    module.exports = object;
    

    全局导出(例如,在浏览器中的window

    global['name'] = object;
    

UMD 包装了一个 factory 函数,该函数负责创建要导出的对象,并将其作为参数传递给 立即调用的函数表达式 (IIFE),如 sn -p 你粘贴了。 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
);

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

【讨论】:

以上是关于构建一个 JavaScript 库,为啥要以这种方式使用 IIFE?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 JavaScript 会错误地进行这种比较? [关闭]

在 Eclipse 中使用 aar - 为啥第 3 方活动在构建时解决而不是运行时解决?

为啥要以初始容量启动 ArrayList?

企业网站制作要以简约为主

为啥交叉构建约定将 scala 版本附加到 artifactId?

为啥在构建依赖库之前没有开始编译目标可执行文件?