锁定老帖子 主题:Javascript 垃圾收集机制
精华帖 (0) :: 良好帖 (0) :: 新手帖 (3) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-10-14
经常使用 Javascript 的人会琢磨其垃圾收集机制,Javascript 并不像 C,C++ 那样需要开发者手动去清除垃圾,在编写 Javascript 程序是,开发者无需关心内存使用问题,所需内存分配以及无用内存(垃圾)的回收完全实现了自动管理。究其根源,主要是程序收集那些不再使用的变量,并且释放其占用的内存。因此,垃圾收集机制会按照固定时间间隔,周期性反复的执行这一操作。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-10-14
学习了。javacript有没有好书介绍下。
|
|
返回顶楼 | |
发表时间:2011-10-14
foible 写道
学习了。javacript有没有好书介绍下。
我个人觉得如果有一定的javascript基础后,去看 《javascript 高级程序设计》- 尼古拉斯·泽卡斯(Nicholas C.Zakas) 就可以了。这哥们写的书挺好的。 |
|
返回顶楼 | |
发表时间:2011-10-14
最后修改:2011-10-14
好像说的有问题吧?
我记得标记法是这样: 从全局开始逐一标记能引用到的各个对象,标记完成后,没有被标记的就是永远不可能被用到的对象,就会被释放。 你对引用计数举的例子分析也有些问题,说到变量就不能脱离作用域链(scope chain),及当前执行环境(activate object) 以你的例子来说: function countMethod(){ // 进入新的函数,当前activate object及作用域链为: activate object = (scope1) -> global // (scope1)引用数为1, global引用数+1 var object1 = new Object(); // 新建的对象(以o1称它)被当前作用域引用:(scope1).object1 = o1 // o1引用数为1 var object2 = new Object(); // 新建的对象(以o2称它)被当前作用域引用:(scope1).object2 = o2 // o2引用数为1 object1.method1 = object2; // object1 计数器 -1,object2 计数器 +1 // 创建o2引用: o1.method1 = object2 // o2引用数为2 object2.method2 = object1; // object1 计数器 +1,object2 计数器 -1 // 创建o1引用: o2.method2 = o1 // o1引用数为2 // 离开countMethod,当前activate object恢复调用前,即: activate object = global // (scope1)引用数为0,释放它,同时它的两个属性object1与object2引用也释放,导致o1 o2引用计算-1 // o1引用数为1,o2引用数为1 <-- 这是最简单的循环引用 } // 定义完countMethod方法(以f1称它),产生两个引用: global.countMethod = f1, f1.[[scope]] = global // f1引用数为1, global引用数+1 // 当前activate object及作用域链为: activate object = global countMethod(); 如果有闭包,根据引用计数就是这样子 function f1(){ // activate object = (scope1) -> global // (scope1)+1=1, global+1 var a = {}; // (scope1).a = o1 // o1+1=1 return function f2(){} // (scope1).f2=f2, f2.[[scope]]=(scope1) // f2+1=1; (scope1)+1=2 // activate object=global // (scope1)-1=1 <-- 还有一个引用,是f2造成的,函数定义会存储当前的作用域 } // global.f1 = f1, f1.[[scope]] = global // f1+1=1, global+1 var b = f1(); // global.b=f2 // f2+1=2 b = null; // global.b=null // f2-1=1 // 此时也是有循环引用,(scope1).f2 = f2, f2.[[scope]] = (scope1) 以上是纯理论上的最简单的引用计数,但是可以看到,非常脆弱。现在不管什么浏览器都是几种方法结合,JS内部的循环引用都能识别。 我们常说的循环引用无法释放是指JS与DOM两套体系之间的循环引用 |
|
返回顶楼 | |
发表时间:2011-10-14
“从全局开始逐一标记能引用到的各个对象,标记完成后,没有被标记的就是永远不可能被用到的对象,就会被释放。” 这句话没错,但是我认为你所说的标记完成,也是对于变量(全局,局部)是否“进入环境”的另外一种说法。变量进入环境,则标记,未进入环境或函数运行完毕后退出环境之后,都会标记为“离开环境”。我们可以从程序获得所有的变量(全局,局部),但是如果没有函数的运行,又怎能确定哪些变量是有用的,从而进行“标记”呢?所以我认为变量“进出环境”为先导条件,有了这个才有了“标记”。没有函数运行环境,无法谈标记。感谢你的回复。相互交流哈。
计数法在IE的支持不是很好,研究的也不多,非常感谢你的指出哈。学习了。谢谢。 |
|
返回顶楼 | |
发表时间:2011-10-14
最后修改:2011-10-14
我学JS时间不长,但是我想理解了这段话。
大概也能知道JS的垃圾机制了吧。 We described it as a list of objects, not a stack of bindings. Each time a JavaScript function is invoked, a new object is created to hold the local variables for that invocation, and that object is added to the scope chain. When the function returns, that variable binding object is removed from the scope chain. If there were no nested functions, there are no more references to the binding object and it gets garbage collected. If there were nested functions defined, then each of those functions has a reference to the scope chain, and that scope chain refers to the variable binding object. If those nested functions objects remained within their outer function, however, then they themselves will be garbage collected, along with the variable binding object they referred to. But if the function defines a nested function and returns it or stores it into a property somewhere, then there will be an external reference to the nested function. It won’t be garbage collected, and the variable binding object it refers to won’t be garbage collected either. 出自 JavaScript.The.Definitive.Guide.6th.Edition |
|
返回顶楼 | |
发表时间:2011-10-14
firefly_zp 写道
“从全局开始逐一标记能引用到的各个对象,标记完成后,没有被标记的就是永远不可能被用到的对象,就会被释放。” 这句话没错,但是我认为你所说的标记完成,也是对于变量(全局,局部)是否“进入环境”的另外一种说法。变量进入环境,则标记,未进入环境或函数运行完毕后退出环境之后,都会标记为“离开环境”。我们可以从程序获得所有的变量(全局,局部),但是如果没有函数的运行,又怎能确定哪些变量是有用的,从而进行“标记”呢?所以我认为变量“进出环境”为先导条件,有了这个才有了“标记”。没有函数运行环境,无法谈标记。感谢你的回复。相互交流哈。
计数法在IE的支持不是很好,研究的也不多,非常感谢你的指出哈。学习了。谢谢。
假如我的脚本就一行
a = 1
那执行完后,这个a是“进入环境”还是“离开环境”状态呢? |
|
返回顶楼 | |
发表时间:2011-10-14
最后修改:2011-10-14
kidneyball 写道
firefly_zp 写道
“从全局开始逐一标记能引用到的各个对象,标记完成后,没有被标记的就是永远不可能被用到的对象,就会被释放。” 这句话没错,但是我认为你所说的标记完成,也是对于变量(全局,局部)是否“进入环境”的另外一种说法。变量进入环境,则标记,未进入环境或函数运行完毕后退出环境之后,都会标记为“离开环境”。我们可以从程序获得所有的变量(全局,局部),但是如果没有函数的运行,又怎能确定哪些变量是有用的,从而进行“标记”呢?所以我认为变量“进出环境”为先导条件,有了这个才有了“标记”。没有函数运行环境,无法谈标记。感谢你的回复。相互交流哈。
计数法在IE的支持不是很好,研究的也不多,非常感谢你的指出哈。学习了。谢谢。
假如我的脚本就一行
a = 1
那执行完后,这个a是“进入环境”还是“离开环境”状态呢?
执行完了,还有环境吗?
|
|
返回顶楼 | |
发表时间:2011-10-15
firefly_zp 写道
“从全局开始逐一标记能引用到的各个对象,标记完成后,没有被标记的就是永远不可能被用到的对象,就会被释放。” 这句话没错,但是我认为你所说的标记完成,也是对于变量(全局,局部)是否“进入环境”的另外一种说法。变量进入环境,则标记,未进入环境或函数运行完毕后退出环境之后,都会标记为“离开环境”。我们可以从程序获得所有的变量(全局,局部),但是如果没有函数的运行,又怎能确定哪些变量是有用的,从而进行“标记”呢?所以我认为变量“进出环境”为先导条件,有了这个才有了“标记”。没有函数运行环境,无法谈标记。感谢你的回复。相互交流哈。
计数法在IE的支持不是很好,研究的也不多,非常感谢你的指出哈。学习了。谢谢。
我还是比较同意你的观点的。 个人理解,函数在未执行前,只是一个定义而已,分配的内存应该只是代码段。只有在当函数执行时,其中的内部变量才会绑定到一个对象,然后添加到scope chain中。
|
|
返回顶楼 | |
发表时间:2011-10-15
psychopath 写道
kidneyball 写道
firefly_zp 写道
“从全局开始逐一标记能引用到的各个对象,标记完成后,没有被标记的就是永远不可能被用到的对象,就会被释放。” 这句话没错,但是我认为你所说的标记完成,也是对于变量(全局,局部)是否“进入环境”的另外一种说法。变量进入环境,则标记,未进入环境或函数运行完毕后退出环境之后,都会标记为“离开环境”。我们可以从程序获得所有的变量(全局,局部),但是如果没有函数的运行,又怎能确定哪些变量是有用的,从而进行“标记”呢?所以我认为变量“进出环境”为先导条件,有了这个才有了“标记”。没有函数运行环境,无法谈标记。感谢你的回复。相互交流哈。
计数法在IE的支持不是很好,研究的也不多,非常感谢你的指出哈。学习了。谢谢。
假如我的脚本就一行
a = 1
那执行完后,这个a是“进入环境”还是“离开环境”状态呢?
执行完了,还有环境吗?
变量声明是在什么地方声明的,是函数体内局部变量还是全局变量?如果是局部变量必然会有其运行环境(子函数内,闭包函数内等等),在包含此局部变量的函数运行结束后(变量 a 没有被其他变量引用),就会被释放。如果是全局变量,当包含这个全局变量的函数体运行结束后,这个变量才会被释放,否则一直在环境内,不会释放的。
单说 a = 1 这个函数声明(如果只有这一行,那就不是 js 了。他必然包含在某个函数中 - 或全局函数或内部函数),a = 1 执行完成后是“进入环境”,因为他被包含于某个函数中,当他被包含于的这个函数执行结束后,并且没有其他变量对他的引用时,这个时候的状态才是“离开环境”。
我们现在所说的“离开环境”的状态主要有两点:第一,变量本身离开其所处的环境(最直接的可以看出)。第二,如果变量被其他变量所引用,则要去判断引用 a 的变量是否离开了他的环境,如果两点都符合,则此时的 a = 1的状态是“离开环境”。 |
|
返回顶楼 | |