Javascript 的作用域链和垃圾回收问题
有如下代码:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
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的一个内部属性里面就行了,后面再调用时直接读取这个内部属性就好了。
1,c1会被释放
2,可以确定。我理解是在解释js的的时候确定的。不过细节不清楚。