Javascript在没有进一步引用后清除变量

时间:2011-03-02 15:16:23

标签: javascript performance

据说,javascript在最后引用后从内存中清除变量。

为了这个问题,我只用一个变量为DEMO 创建了一个 JS文件;

//file start 

//variable defined
var a=["Hello"]

//refenence to that variable
alert(a[0]);

//
//file end

没有进一步引用该变量,所以我希望javascript清除变量'a'

现在我只是运行了这个页面,然后打开了firebug并运行了这段代码

alert(a[0]);

现在这会警告变量的值,如果语句“Javascript在没有进一步引用后清除变量”,则为什么alert()会显示其值。

是因为全局上下文中定义的所有变量都成为window对象的属性,因为即使在执行文件窗口对象存在之后也是如此。

5 个答案:

答案 0 :(得分:4)

当然,在这个例子中要保留变量HAS - 毕竟,你保持环境已被定义在周围。只要你仍然可以访问它就必须保留,所以如果你可以进行这个测试并且它失败了 - 那么JS解释器就是“kaputt”。

请改为:

(function () {
  var a = 1;
}());

// and NOW, at THIS point there is nothing any more referencing "a"

当然,从“这里”你不能测试 - 你必须看看JS解释器/编译器的内部存储器结构(今天在V8的时代它更像是“interpiler”或“compreter” “aynway)。

此外,与所有垃圾收集(GC)语言一样,内存不会立即释放,而是取决于Javascript的特定实现所使用的GC策略,这也考虑了当前的内存使用和需求。 GC是一项代价高昂的操作,如果可能的话会延迟和/或在不从实际应用程序中夺走CPU资源时运行。

顺便说一句,略有变化:

(function () {
  var a = 1;
  //empty function assigned to global namespace,
  //in browsers "window" is the global object
  window.example_function = function () {};
}());

在此示例中,结果与您的结果相同:只要您查看该页面,“a”的内存永远不会释放:分配给全局对象的属性example_function的函数仍然存在,因此所有环境被定义为必须保留!只有在

之后
delete window.example_function

从全局对象中删除该属性 - 最后是指向(空)函数表达式的指针,可以释放变量“a”。另请注意,该功能甚至不使用“a”,请参阅Google并搜索“词法范围”,这是Javascript语言最具定义性的属性之一。

更有趣:

我写过

//define a variable in global namespace
var example_function;

(function () {
  var a = 1;
  //empty function assigned to global namespace,
  //in browsers "window" is the global object
  example_function = function () {};
}());

我无法使用“删除”删除它,实际上我无法释放它。这是因为在第一个示例中,example_function成为全局对象(强调)的新属性,而在最后一个示例中,它是一个变量,“delete”仅适用于对象属性。 (我在前面的例子中使用了“windows.example_function”,但没有“window”。它本来就是一样的,example_function会在全局对象中创建为属性。只有“var”语句才会创建变量。)

答案 1 :(得分:2)

  

是因为全局上下文中定义的所有变量都成为window对象的属性,因为即使在执行文件窗口对象存在之后也是如此。

是。您可能必须关闭窗口,或者从窗口属性中明确删除a

答案 2 :(得分:2)

您的脚本的副作用是在全局对象(窗口)中定义了属性名称“a”,因此实际上仍然存在对a的全局引用。

(function()
{
  var a = 12;
  alert(a);
})();

如果我们将此处的自执行函数的声明包装起来,则在函数退出后将无法访问该函数。

答案 3 :(得分:2)

是的,尽管您可以通过在函数范围内声明并处理变量来缓解此行为:

( function myfunc(a){
  var b = 100;
  alert(a); // 200
  alert(b); // 100
}(200));

alert(a); // undefined
alert(b); // undefined

答案 4 :(得分:0)

引用变量并不意味着以某种方式使用它。只要至少有一个对仍然可以访问的变量的引用,它必须保存在内存中。

查看您的示例,以下行对变量是否被清除没有影响。即使a没有在任何地方使用,它仍然保持不变。

//refenence to that variable
alert(a[0]);

尽管可以在函数内部创建对象,但其生命周期可能超出函数本身。唯一要记住的是是否仍然存在对相关对象的任何有效引用。考虑这个example

(function() {
    var a = ["Hello"];
    var copy = a;
    a = null;

    setTimeout(function() {
        // a: null, copy: ["Hello"]
        console.log("a: %o, copy: %o", a, copy);
    }, 2000);
})();

变量a在匿名函数内创建,另一个变量copy正在引用它。 a之后设置为null,但我们仍然可以从copy获得1个引用。然后我们创建一个超时,它会对同一个变量进行另一次引用。现在即使这个匿名函数在执行setTimeout后超出范围,我们仍然在超时函数中留下1个引用。因此,当运行超时函数时,此copy变量仍将保持不变。