当前位置: 首页 > 知识库问答 >
问题:

关于未引用变量的JavaScript闭包

蓬森
2023-03-14
function foo() {
    var x = {};
    var y = "whatever";

    return function bar() {
        alert(y);
    };
}

var z = foo();

bar中引用Y调用闭包,只要在垃圾回收器周围保留Z就不会清理Y。问题是--x会发生什么?即使它没有被引用,它也是由那个闭包持有的吗?垃圾回收器是否会看到没有引用x并将其清理掉?还是只要我坚持zX就会与Y一起存在?(理想的答案是引用ECMA规范。)

共有1个答案

林富
2023-03-14

问题是,x会发生什么?

答案因理论和实施而异。

理论上,是的,X保持活动,因为闭包(匿名函数)引用了调用foo上下文的绑定对象,其中包括X

x = undefined;

让我们看看V8中使用Chrome堆快照特性的代码:

function UsedFlagClass_NoFunction() {}
function UnusedFlagClass_NoFunction() {}
function build_NoFunction() {
  var notused = new UnusedFlagClass_NoFunction();
  var used = new UsedFlagClass_NoFunction();
  return function() { return used; };
}

function UsedFlagClass_FuncDecl() {}
function UnusedFlagClass_FuncDecl() {}
function build_FuncDecl() {
  var notused = new UnusedFlagClass_FuncDecl();
  var used = new UsedFlagClass_FuncDecl();
  function unreachable() { notused; }
  return function() { return used; };
}

function UsedFlagClass_FuncExpr() {}
function UnusedFlagClass_FuncExpr() {}
function build_FuncExpr() {
  var notused = new UnusedFlagClass_FuncExpr();
  var used = new UsedFlagClass_FuncExpr();
  var unreachable = function() { notused; };
  return function() { return used; };
}

window.noFunction = build_NoFunction();
window.funcDecl = build_FuncDecl();
window.funcExpr = build_FuncExpr();

下面是展开的堆快照:

在处理build_noffunction函数时,V8成功地识别出无法到达从notused引用的对象并将其删除,但在其他任何一个场景中都不会这样做,尽管无法到达unreachable,因此无法通过它到达notused

function UsedFlagClass_NoFunction() {}
function UnusedFlagClass_NoFunction() {}
function build_NoFunction() {
    new UnusedFlagClass_NoFunction;
    var a = new UsedFlagClass_NoFunction;
    return function () {
        return a
    }
}

function UsedFlagClass_FuncDecl() {}
function UnusedFlagClass_FuncDecl() {}
function build_FuncDecl() {
    new UnusedFlagClass_FuncDecl;
    var a = new UsedFlagClass_FuncDecl;
    return function () {
        return a
    }
}

function UsedFlagClass_FuncExpr() {}
function UnusedFlagClass_FuncExpr() {}
function build_FuncExpr() {
    new UnusedFlagClass_FuncExpr;
    var a = new UsedFlagClass_FuncExpr;
    return function () {
        return a
    }
}
window.noFunction = build_NoFunction();
window.funcDecl = build_FuncDecl();
window.funcExpr = build_FuncExpr();

正如您所看到的,静态分析告诉CCunreachable是死代码,因此它完全删除了它。

但是当然,您可能在函数执行过程中使用unreachable,而在函数完成后就不需要它了。它不是死代码,但它是当函数结束时你不需要的代码。在这种情况下,您必须求助于:

unused = undefined;

在最后。由于您不再需要该函数,您还可以释放它:

unused = unreachable = undefined;
unreachable = undefined;
 类似资料:
  • 问题内容: 我试图设置一个变量,该变量位于该闭包内部的闭包外部,但最终不会被设置。然而,我设置变量的值 是 正在打印到控制台。同样,在设置返回变量并自行打印之后,将正确的值打印到控制台。当我返回变量时就会出现问题。其值与初始化时的值相同。这是一些伪代码: 这是不起作用的实际代码: 问题答案: .observeSingleEvent正在异步工作。 您可以执行以下操作: 然后,您可以在任何需要的地方使

  • 问题内容: 我正在努力使用WindowListener关闭JFrame。 我遇到一种情况,客户端登录到服务器,并且当客户端关闭其应用程序时,需要通知服务器。因此,为了通知服务器,应该处理一个类的另一个实例(处理rmi实现)。该实例是我的GUI类中的全局变量。 我在网上搜索了一下,但我能解决的唯一问题是以下结构 这里的问题是我不能使用全局变量。有人可以帮助我解决这个问题吗? 问题答案: 在过去,当我

  • 本文向大家介绍浅谈PHP中关于foreach使用引用变量的坑,包括了浅谈PHP中关于foreach使用引用变量的坑的使用技巧和注意事项,需要的朋友参考一下 写PHP好多年,但仍然会犯低级错误,今天遇到个 foreach中引用变量时的坑,PHP版本为 5.6.12 代码如下: 输出结果 一开始看到第二个 foreach 输出的结果感觉很是莫名其妙,怎么会输出两个 d_d 呢? 仔细想了想,原来因为P

  • 问题内容: Go编译器不应该将循环变量捕获为本地分配的闭包变量吗? 长版: 这也引起了我对C#的困惑,并且我试图理解它。这就是为什么它在C#5.0中已得到修复(原因:循环变量 不能 在循环体内改变)以及未在C#循环中对其进行修复的原因(原因:循环变量 可以 在循环体内改变)。 现在(对我而言),Go中的循环看起来很像C#中的循环,但是尽管事实是我们无法更改这些变量(例如和中)。仍然我们必须首先将它

  • 想象一下我有: 输出: 我想要的是: 现在,正如我所说,这并没有把x设为3,而是把y设为3。我怎样才能改变它,使y充当指向x的指针。我想编辑x,而不是y。之前,我相信我看到了一个关于使用可变变量的页面。我不认为我完全理解Python中变量是如何工作的。

  • 我正在尝试使用HTML、CSS和Javascript制作一个简单的哑巴井字游戏。 在下面的播放器移动函数中,由于JSON对象中存在Typeerror,因此无法调用ComputerMove函数。 下面是JSON对象:- 检查功能始终有效,控制台响应如下 调试时,我发现在此错误之后,计算机移动()函数永远不会被调用。所以请帮忙。