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

Jus*_*rce 8 javascript garbage-collection scope anonymous-function

我的直觉是,在这样的匿名函数中封装代码块是个好主意:

(function() {
  var aVar;
  aVar.func = function() { alert('ronk'); };
  aVar.mem = 5;
})();
Run Code Online (Sandbox Code Playgroud)

因为我不再需要aVar了,所以我假设垃圾收集器会aVar在超出范围时删除.这是正确的吗?或者是口译员足够聪明,看到我不再使用变量并立即清理它?是否有任何理由,如风格或可读性,我应该使用匿名函数这种方式?

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

var operations = function() {
  var aVar;
  aVar.func = function() { alert('ronk'); };
  aVar.mem = 5;
};
operations();
Run Code Online (Sandbox Code Playgroud)

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.

})();
Run Code Online (Sandbox Code Playgroud)

我的假设和结论是否正确?每当我不打算重复使用的模块,我不应该只将其封装在一个功能,但在一个匿名函数封装它,这样的函数没有引用,这就是所谓后删除了,对不对?

Chu*_*uck 4

你是对的,将变量粘贴在匿名函数中是避免弄乱全局对象的好习惯。

\n\n

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

\n\n

本质上,记住两件事:

\n\n
    \n
  1. 只要有一个对象存在,如果没有您的同意,它的任何插槽都不会被神奇地释放。
  2. \n
  3. 在全局上下文中声明的变量是全局对象的槽(window在客户端 Javascript 中)。
  4. \n
\n\n

总而言之,这些意味着全局变量中的对象在脚本的生命周期内持续存在(除非重新分配变量)。这就是为什么我们声明匿名函数 \xe2\x80\x94 变量获得一个新的上下文对象,该对象在函数完成执行后立即消失。除了提高效率之外,它还减少了名称冲突的机会。

\n\n

不过,您的第二个示例(使用内部匿名函数)可能有点过于热心。我不担心“帮助垃圾收集器”,\xe2\x80\x94 GC 可能不会在该函数中间运行。担心那些会持续保留的东西,而不仅仅是比原本保留的时间稍长一些。这些自动执行的匿名函数基本上是自然归属在一起的代码模块,因此一个好的指南是考虑这是否描述了您正在做的事情。

\n\n

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

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

这会导致点击回调捕获该巨大的数组,使其永远不会消失。您可以通过在其自己的函数内隔离数组来避免这种情况。

\n