我的直觉是,在这样的匿名函数中封装代码块是个好主意:
(function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
})();
因为我不再需要aVar
,所以我假设垃圾收集器会在超出范围时删除aVar
。这是正确的吗?或者是口译员足够聪明,看到我不再使用变量并立即清理它?我是否不以这种方式使用匿名函数是否有任何风格或可读性等原因?
另外,如果我将该功能命名为:
var operations = function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
};
operations();
operations
然后必须坚持下去,直到它超出范围?或者,口译员能否立即告知何时不再需要它?
我还想澄清一点,我不一定在谈论全球范围。考虑一个看起来像
的块(function() {
var date = new Date(); // I want to keep this around indefinitely
// And even thought date is private, it will be accessible via this HTML node
// to other scripts.
document.getElementById('someNode').date = date;
// This function is private
function someFunction() {
var someFuncMember;
}
// I can still call this because I named it. someFunction remains available.
// It has a someFuncMember that is instantiated whenever someFunction is
// called, but then goes out of scope and is deleted.
someFunction();
// This function is anonymous, and its members should go out of scope and be
// deleted
(function() {
var member;
})(); // member is immediately deleted
// ...and the function is also deleted, right? Because I never assigned it to a
// variable. So for performance, this is preferrable to the someFunction
// example as long as I don't need to call the code again.
})();
我的假设和结论是否正确?每当我不打算重用一个块时,我不应该只将它封装在一个函数中,而是将它封装在一个匿名函数中,这样该函数就没有引用,并在被调用后被删除,对吗?
答案 0 :(得分:4)
你是对的,将变量放在匿名函数中是一种很好的做法,可以避免使全局对象混乱。
回答后两个问题:解释器完全不可能知道只要有一个全局可见的引用,对象就不会再被使用。对于所有解释器都知道,您可以随时评估一些依赖于window['aVar']
或window['operation']
的代码。
基本上,请记住两件事:
window
)。组合,这意味着全局变量中的对象持续脚本的生命周期(除非重新分配变量)。这就是我们声明匿名函数的原因 - 变量获得一个新的上下文对象,一旦函数完成执行就会消失。除了效率获胜之外,它还减少了名称冲突的可能性。
你的第二个例子(使用内部匿名函数)可能有点过于热心。我不担心“帮助垃圾收集器” - GC可能不会在中间运行,无论如何。担心会持续存在的事情,而不仅仅是比其他情况稍长的事情。这些自执行的匿名函数基本上是代码模块,它们自然属于一体,因此一个好的指南就是考虑它是否描述了你正在做的事情。
但是有理由在匿名函数中使用匿名函数。例如,在这种情况下:
(function () {
var bfa = new Array(24 * 1024*1024);
var calculation = calculationFor(bfa);
$('.resultShowButton').click( function () {
var text = "Result is " + eval(calculation);
alert(text);
} );
})();
这导致巨大的数组被点击回调捕获,因此它永远不会消失。您可以通过将数组隔离在自己的函数中来避免这种情况。
答案 1 :(得分:1)
您添加到全局范围的任何内容都将保留在那里,直到页面被卸载(除非您专门删除它)。
将变量和函数放在局部作用域或对象中通常是一个好主意,这样它们就可以尽可能少地添加到全局名称空间中。这样,重用代码就容易多了,因为您可以在页面中组合不同的脚本,而命名冲突的风险最小。