我应该在匿名JavaScript函数中封装功能块吗?

我应该在匿名JavaScript函数中封装功能块吗?,javascript,garbage-collection,scope,anonymous-function,Javascript,Garbage Collection,Scope,Anonymous Function,我的直觉是,最好将代码块封装在匿名函数中,如下所示: (function() { var aVar; aVar.func = function() { alert('ronk'); }; aVar.mem = 5; })(); var operations = function() { var aVar; aVar.func = function() { alert('ronk'); }; aVar.mem = 5; }; operations(); 因为我不再需要a

我的直觉是,最好将代码块封装在匿名函数中,如下所示:

(function() {
  var aVar;
  aVar.func = function() { alert('ronk'); };
  aVar.mem = 5;
})();
var operations = function() {
  var aVar;
  aVar.func = function() { alert('ronk'); };
  aVar.mem = 5;
};
operations();
因为我不再需要
aVar
,所以我假设垃圾收集器在超出范围时会删除
aVar
。是这样吗?或者解释器是否足够聪明,可以看到我不再使用变量并立即清理它?是否有任何原因,例如样式或可读性,我应该而不是以这种方式使用匿名函数

另外,如果我命名函数,如下所示:

(function() {
  var aVar;
  aVar.func = function() { alert('ronk'); };
  aVar.mem = 5;
})();
var operations = function() {
  var aVar;
  aVar.func = function() { alert('ronk'); };
  aVar.mem = 5;
};
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.

})();

我的假设和结论正确吗?每当我不打算重用一个块时,我不仅应该将它封装在一个函数中,而且应该将它封装在一个匿名函数中,这样该函数就没有引用,并且在调用后被删除,对吗?

添加到全局作用域的任何内容都将保留在那里,直到页面卸载为止(除非您特别删除它)


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

您是对的,在匿名函数中粘贴变量是避免全局对象混乱的一种好做法

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

基本上,记住两件事:

  • 只要有一个物体在周围,没有你的许可,它的任何插槽都不会被神奇地释放
  • 全局上下文中声明的变量是全局对象的插槽(
    window
    在客户端Javascript中)
  • 结合起来,这意味着全局变量中的对象将在脚本的生命周期内持续(除非重新分配该变量)。这就是我们声明匿名函数的原因——变量得到一个新的上下文对象,该对象在函数完成执行后立即消失。除了提高效率外,它还减少了名称冲突的机会

    不过,您的第二个示例(使用内部匿名函数)可能有点过于热心。我不会担心“帮助垃圾收集器”在那里- GC可能不会运行在中间的那个函数无论如何。担心会持续存在的事情,而不仅仅是比其他事情稍微长一点。这些自动执行的匿名函数基本上是自然地属于一起的代码模块,因此一个很好的指南是考虑这是否描述了您正在做的事情

    不过,在匿名函数中使用匿名函数是有原因的。例如,在这种情况下:

    (function () {
      var bfa = new Array(24 * 1024*1024);
      var calculation = calculationFor(bfa);
      $('.resultShowButton').click( function () {
        var text = "Result is " + eval(calculation);
        alert(text);
      } );
    })();
    

    这将导致单击回调捕获这个巨大的数组,这样它就永远不会消失。你可以通过在自己的函数中隔离数组来避免这个问题。

    只是好奇,有没有考虑内存泄漏?对吧?我同意这一点。我的问题更多的是,将单个代码块粘贴在匿名函数中是否有利于真正最小化它们的作用域。一个例子可能是我一直保留的一个对象,可能是通过将它指定为HTML节点的一个成员,但是其中的一个单独的块可以完成它的任务,然后被删除。我想我的问题更多的是关于垃圾收集的细节,以及我应该让垃圾收集在多大程度上影响我的风格。我理解并同意将此作为一种避免全局命名空间混乱的措施。我认为我最初的例子没有充分说明我问题的范围。我修改了我的问题,加入了一个更好的例子。担心那些会持续存在的东西,而不是比其他情况稍微长一点。那正是我要找的!谢谢你的帮助!