【问题标题】:Using self-executing anonymous functions inside the revealing module pattern在显示模块模式中使用自执行匿名函数
【发布时间】:2011-10-04 17:43:31
【问题描述】:

只是想知道这是否是一种好的 JavaScript 实践。

假设我有很多网页都调用初始化函数“init()”,每次加载脚本时在我的模式中使用IIFE 来运行该函数是否正确?

var foo = (function() {
    var bar = "something";

    (function init() {
        // Do something crazy that's gonna be the same across all my web pages
        // like adding an event listener or something
        // ...
        document.write('page init...');
    }());

    function privatePage1() {
        // This stuff is gonna be used only in page1.html via foo.privatePage1
        document.write('page 1' + bar);
    }

    function privatePage2() {
        // This stuff is gonna be used only in page2.html via foo.privatePage2
        document.write('page 2' + bar);
    }

    return {
        privatePage1: privatePage1,
        privatePage2: privatePage2
    }
}());

【问题讨论】:

  • 您必须显示更多相关代码,然后我们才能为您的案例提供正确的答案。使用匿名函数通常是一种很好的做法,因为泄漏的变量更少。

标签: javascript design-patterns iife


【解决方案1】:

这是一个相当主观的领域,但这是我的看法:

  • 当您使用模块模式时,您为代码的其余部分提供了一组包含的功能。它本质上是一个迷你图书馆。

  • 一般来说,我不希望库在我加载它时任何事情,除了初始化步骤完全在库内部(例如,设置配置、实例化一些必要的对象等)——实际上没有任何东西会影响 DOM 或以其他方式显着改变环境(这就是为什么我对更改原型的 Date.js 或 Prototype 之类的库并不完全满意的原因基本对象)。

  • 这有几个原因,但主要原因是我不想担心我的库/模块的加载顺序,除了简单地管理依赖关系。独立的模块不应该相互影响。当您在加载时操作模块中的 DOM 时,迟早您会意识到另一段代码期望 DOM 在某个时间处于某个状态,您现在必须关心您是否在该时间之前或之后加载您的模块。这是一个额外的复杂性,基本上隐藏在加载模块的脚本标签中。

  • 这里的另一个问题是可移植性和适应性。也许你会想在另一个项目中使用你的模块和另一个 DOM 设置。也许您希望将不同的 DOM 元素或配置变量传递给特定页面上的 init() 函数。如果你自动执行init(),你就失去了配置的机会。

所以我一般做的是将init()方法设置为返回模块对象的一个​​属性:

var foo = (function() {

    function init() {
        // Do something crazy that's gonna be the same across all my web pages
    }

    //...

    return {
        init: init,
        // etc
    }
}());

然后根据需要在我的代码中的其他地方调用它:

foo.init();

是的,这为我的所有页面的初始化添加了一行额外的冗余代码(尽管这可能只是另一个脚本,所以添加的权重是全部 11 个字符)。但它允许我更细粒度地控制模块的初始化时间,并在我(不可避免地)确定以后需要配置参数时为配置参数提供挂钩。

【讨论】:

  • 很好的答案。现在我也返回了 init() 函数,但想知道是否可以节省在每个页面中调用它的额外步骤。你的论点很有道理!
  • 非常感谢您对模块在加载时不执行任何操作的评论。我正在编写我的第一个真正的 js 模块,并被指示使用“显示模块”,在这种情况下,它更像是一个“隐藏模块”,因为没有 init,它真的不需要显示任何东西。您对init 的建议给了我一个很好的开始。
【解决方案2】:

init() 功能在网页中是否相同?如果是这样,我会这样做:

var foo = (function()
{
    init();
    return {};
}());

如果没有,我看不出使用 IIFE 的理由,并且会像这样简化您的原始代码:

var foo = (function()
{
    /* body of the original IIFE here */
    return {};
}());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多