在显示模块模式中使用自执行匿名函数

时间:2011-10-04 17:43:32

标签: javascript design-patterns iife

只是想知道这是一个很好的JavaScript练习。

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

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
    }
}());

2 个答案:

答案 0 :(得分:6)

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

  • 使用模块模式时,您将为其余代码提供一组包含的功能。它本质上是一个小型图书馆。

  • 一般情况下,除了完全内部到库的初始化步骤之外,我加载它时,我不希望库任何东西。例如,设置配置,实例化一些必要的对象等) - 没有任何实际影响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个字符)。但它允许我对模块初始化时进行更细粒度的控制,并在我(不可避免地)确定我以后需要它时提供配置参数的挂钩。

答案 1 :(得分:1)

网页中的init()功能是否相同?如果是这样,这就是我要做的事情:

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

如果没有,我认为没有理由使用IIFE,并且会简化你原来的代码:

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