只是想知道这是一个很好的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
}
}());
答案 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 {};
}());