2010-09-20 82 views
7

我的直觉是,它的封装在匿名函数的代码块这样一个好主意:我应该在匿名JavaScript函数中封装功能块吗?

(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

只是好奇,有没有考虑内存泄漏? – jebberwocky 2010-09-20 17:03:59

回答

4

你说得对,在匿名函数中粘贴变量是避免混淆全局对象的一个​​好习惯。

回答你的后两个问题:解释者完全不可能知道一个对象只要有全局可见的引用就不会再被使用。对于所有的翻译知道,你可以随时评估一些依赖于window['aVar']window['operation']的代码。

从本质上讲,记住两点:

  1. 只要对象是各地的,没有它的插槽将被奇迹般地没有你说那么释放。
  2. 在全局上下文中声明的变量是全局对象(客户端Javascript中的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); 
    }); 
})(); 

这导致了巨大的阵列被点击的回调使得它永远不会消失抓获。你可以通过在自己的函数中隔离数组来避免这种情况。

+0

我理解并同意将此作为避免混淆全局名称空间的措施。我认为我最初的例子没有充分证明我的问题的范围。我修改了我的问题以包含更好的示例。 – 2010-09-20 17:52:59

+0

_纠结将永久保持的事情,不只是稍微长于他们本来的时间。 这正是我所期待的!谢谢你的帮助! – 2010-09-21 06:22:04

1

任何添加到全局范围的内容都会一直保留,直到页面被卸载(除非您专门删除它)。

将属于一起的变量和函数放在本地范围或对象中,以便尽可能少地添加到全局名称空间通常是一个好主意。这样一来,重用代码就容易多了,因为您可以在页面中组合不同的脚本,并将命名冲突的风险降至最低。

+0

没错。我同意这一点。我的问题更多的是将匿名函数中的各个代码块放在最小范围内是否合适。一个例子可能是一个对象,我可能通过将它分配为HTML节点的成员,但其中的一个块可能只是做它的事情,然后被删除。我想我的问题更多的是垃圾收集的细节,以及我应该让我的风格告诉我多少。 – 2010-09-20 17:37:30