Javascript 的作用域链和垃圾回收问题

发布于 2022-09-02 09:38:42 字数 406 浏览 16 评论 0

有如下代码:

function f1(){
    var a1 = 1;
    var b1 = 2;
    var c1 = 3;
    function f2(){
        var a2 = a1;
        function f3(){
            var a3 = b1;
            return a3;
        }
    }
    return f2;
}
var f = f1();
...

两个自认为密切相关的问题的问题:
1、假如在var f = f1();之后垃圾回收器被触发,f1被调用时生成的局部变量是全部被保留,还是c1会被回收?
2、f1函数返回的时候,js引擎是否能够确定f2函数内部需要使用的闭包变量,如果是,是在什么时候确定的?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱要勇敢去追 2022-09-09 09:38:42

JS引擎有很多不同实现。我没有读过任何JS引擎的源码,所以不敢乱说。只从ES规范的角度简单说一下。

  • 问题一:
    c1保留还是不保留都是可以的。方案一:c1保留;方案二:c1不保留。不过根据我对Chrome浏览器的测试,c1不会保留,说明webkit引擎采取了方案二。

  • 问题二:
    与问题一中两种方案采取哪一种有关。假设某个JS引擎采取了方案一,那么问题就简单了。根据ES规范:

函数对象中有一个指向外部词法环境的引用(指针)。

根据我的理解,这是形成闭包的根本原因。也就是说,在f2被定义的时候,f2这个函数有一个叫做f2.scope的内部属性。它指向定义f2这个函数的词法环境,也就是f1执行时生成的词法环境,这个词法环境里面保存了a1、b1和c1等变量。所以在f1执行完返回后,只要f2还存在,它仍然可以访问f1的局部变量。这里面的基本原理就是:

被引用的变量不会被垃圾回收。

所以,假设JS引擎采取方案一,那么它根本不用关心f2用到了f1的哪些局部变量。你用到谁时自己去取就是了,反正它们一直都存在。

但是如果采取方案二(为了不让那些不需要的局部变量占内存),那么JS引擎实现起来就麻烦一些了,我猜它会在f1返回前去扫描内部的函数定义,例如f2和f3的源码,以确定哪些变量没有被内部函数引用,可以释放了。为什么是函数返回前去扫描呢?因为我们知道,函数返回前正是释放局部变量的时候嘛。

当然,由于f1可能会被调用很多次,从而返回很多次。不能每次都傻乎乎地扫描一遍啊。所以JS引擎可能只在第一次返回时扫描,然后把结果记录在f1的一个内部属性里面就行了,后面再调用时直接读取这个内部属性就好了。

温柔女人霸气范 2022-09-09 09:38:42

1,c1会被释放
2,可以确定。我理解是在解释js的的时候确定的。不过细节不清楚。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文