Fra*_*ent 2 javascript design-patterns iife
只是想知道它是否是一个很好的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
}
}());
Run Code Online (Sandbox Code Playgroud)
这是一个相当主观的领域,但这是我的看法:
当您使用模块模式时,您将为其余代码提供一组包含的功能.它本质上是一个小型图书馆.
一般情况下,我不希望库在加载时做任何事情,除了完全在库内部的初始化步骤(例如设置配置,实例化一些必要的对象等) - 没有任何实际影响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
}
}());
Run Code Online (Sandbox Code Playgroud)
然后在我的代码中的其他位置调用它:
foo.init();
Run Code Online (Sandbox Code Playgroud)
是的,这为我的所有页面的初始化添加了额外的冗余代码行(尽管这可能只是另一个脚本,所以增加的权重是11个字符).但它允许我对模块初始化时进行更精细的控制,并在我(不可避免地)确定我以后需要它时提供配置参数的挂钩.