【问题标题】:Does Javascript closure always retain scope variables?Javascript 闭包是否总是保留范围变量?
【发布时间】:2013-09-23 22:21:13
【问题描述】:

我了解闭包中的代码可以访问作用域链上的变量、方法和参数, 但是如果它不使用它们中的任何一个会发生什么?这些变量还保留吗?

考虑这种情况:

function f(){

  var a=[];
  for(var i=0;i<1000000;i++) a.push({});

  return function(){
     alert('Hi');
  };

}

var x = f();

变量a 是否保留在内存中,即使闭包不使用它?

谢谢

更新: 似乎没有关于“微不足道”的闭包的答案。 那么假设每个闭包(即使它什么都不做)都可以在内存中保留作用域链上的所有方法,包括它们的参数、变量和内部函数(直到闭包被垃圾回收),这是否公平?

此外,关于 node.js 的“可能重复”问题 - 据我所知,node.js 仅在基于 google 的 v8 JS 引擎的专用环境中运行。这里我说的是可以在任何现代浏览器中运行的网络应用程序(在大多数情况下)

【问题讨论】:

  • 你永远无法真正知道...... JS 实现可以为所欲为。进行静态代码分析的聪明垃圾收集器可以收集值,但不能保证。
  • garbage collection with node.js 的可能重复项(及其相关问题)
  • 经验法则:对于带有愚蠢垃圾收集器的(旧)引擎,最好明确设置a=null
  • 如果我们只假设相对较新的浏览器,这是一个需要担心的问题吗?

标签: javascript memory closures


【解决方案1】:

当解释器选择释放它占用的内存是一个实现细节 - 没有单一的 javascript 解释器。

请注意,解释器并不总是可能知道变量未使用:

function f() {
    var a = 123

    return function(x) {
        alert(eval(x));  // if there's an eval, we have to hold onto all local variables
    };

}

f()('a')

在 chrome 控制台中进行实验

var e = eval

var f = function(){
    var a = 123;
    
    return function() {
        return eval('a');
    };
};

var g = function(){
    var a = 123;

    return function() {
        return e('a');
    };
};


f()()  // 123
g()()  // ReferenceError

看来 V8 正在基于 eval 的存在进行优化

【讨论】:

  • this answer 更清楚地说明了正在发生的事情。很高兴看到规范。
  • 不,它不仅看起来很无辜,而且无辜的。 g('a')eval('a') 的评估方式不同,EcmaScript specially introduced the concept of a "direct call" 为此。 g 将评估全局范围内的代码。
  • 这很公平。但我说的是仅使用参数和/或局部变量的几行特别琐碎的函数。新浏览器是否知道如何处理它并表现得像它是一个全局范围方法?这很重要,因为我有一些用于快速事件处理程序设置的小闭包(特别是谈话 - ExtJs 组件侦听器)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
  • 2014-09-07
  • 1970-01-01
  • 1970-01-01
  • 2010-10-26
相关资源
最近更新 更多