JS垃圾回收——和其他语言一样,JavaScript 的 GC 策略也无法避免一个问题:GC 时,停止响应其他操作,这是为了安全考虑
2017-12-28 11:23
477 查看
JavaScript 内存管理 & 垃圾回收机制
标记清除
js 中最常用的垃圾回收方式就是标记清除。当变量进入环境时,例如,在函数中声明一个变量,就将这个而变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。引用计数
这是最简单的垃圾收集算法。此算法把“对象是否不再需要”简化定义为“对象有没有其他对象引用它”。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。Netscape Navigator3 是最早使用引用计数策略的浏览器,但很快它就遇到了一个严重的问题:循环引用。循环引用指的是对象 A 中包含一个指向对象 B 的指针,而对象 B 中也包含一个指向对象 A 的引用。
1 2 3 4 5 6 7 | function fn() { var a = {}; var b = {}; a.pro = b; b.pro = a; } fn(); |
最简单的方式就是自己手工解除循环引用,比如刚才的函数可以这样
1 2 | myObject.element = null; element.o = null; |
内存管理
1、什么时候触发垃圾回收?垃圾回收周期性运行,如果分配的内存非常多,那么回收工作也会很艰巨,确定垃圾回收时间间隔就变成了一个值得思考的问题。IE6 的垃圾回收是根据内存分配量运行的,当环境中存在 256 个变量、4096 个对象、64K 的字符串任意一种情况的时候就会触发垃圾回收器工作,看起来很科学,不用按一段时间就调用一次,有时候会没必要,这样按需调用不是很好嘛?但是如果环境中就是有这么多变量一直存在,现在脚本如此复杂,很正常,那么结果就是垃圾回收器一直在工作,这样浏览器就没法玩了。
微软在 IE7 中做了调整,触发条件不再是固定的,而是动态修改的,初始值和IE6相同,如果垃圾回收器回收的内存分配量低于程序占用内存的 15%,说明大部分内存不可被回收,设的垃圾回收触发条件过于敏感,这时候把临界条件翻倍,如果回收的内存高于 85%,说明大部分内存早就该清理了,这时候把触发条件置回。这样就使垃圾回收工作智能了很多。
2、合理的 GC 方案
1)、JavaScript 引擎基础 GC 方案是(simple GC):mark and sweep(标记清除),即:
遍历所有可访问的对象。
回收已不可访问的对象。
2)、GC 的缺陷
和其他语言一样,JavaScript 的 GC 策略也无法避免一个问题:GC 时,停止响应其他操作,这是为了安全考虑。而 JavaScript 的 GC 在 100ms 甚至以上,对一般的应用还好,但对于 JS 游戏,动画连贯性要求比较高的应用,就麻烦了。这就是新引擎需要优化的点:避免 GC 造成的长时间停止响应。
总结
一般不用 setInterval,而用 setTimeout 的延时递归来代替 interval。setInterval 会产生回调堆积,特别是时间很短的时候。
扩展
setInterval 有个很烦的地方就是当 js 主程序空闲的时候,执行代码队列里面的代码的时候,如果此时候我们有一个问题,定时器是等到回调执行完,才开始计时进行下次循环呢?还是只要一次计时完毕,插入回调之后不管回调执不执行就开始计时呢?答案显示是后者,这也就是我说 setInterval 坑的原因啊,因为这会出现一种情况,当我们插入回调的时候前队列有别的代码在执行,这时候回调肯定是不会执行的,因此如果这个时候无限定时时间到了会再次插入回调,这个时候如果发现队列中的第一次回调没有执行,那么再次插入的回调浏览器就默认取消,(这是以防出现回调连续执行多次的情况)但是这又引发了新的情况就是有些回调是不能取消掉的?相关文章推荐
- 一个JS图片放大镜,实现动态记录的图片放大,避免内存泄露,解决IE6下无法遮盖select控件问题
- HA切换问题: 选主+(切换虚拟ip,启动其他服务 或者 开始调用下游) 无法操作另外一个挂掉的主的情况,脑裂问题
- 在一个webview里跳转到新的activity里,webview无法响应js事件的问题
- 避免网站在IE6中出现‘无法打开站点,已终止操作’的JS问题
- 一个JS图片放大镜,实现动态记录的图片放大,避免内存泄露,解决IE6下无法遮盖select控件问题
- 用c#操作excel无法引入库的问题一个
- 一个关于VS2008在其他未安装VS2008的电脑上无法运行编译的程序的问题 收藏
- “无法更新EntitySet“*****”,因为它有一个DefiningQuery,而<ModificationFunctionMapping>元素中没有支持当前操作的<InsertFunction>元素”问题的解决方法
- .NET----使用母版页后,控件名称自动生成导致js无法正常操作.net控件的问题
- .NET有垃圾回收机制,但是一样会有内存泄漏问题
- “无法更新EntitySet“*****”,因为它有一个DefiningQuery,而元素中没有支持当前操作的元素”问题的解决方法
- 为了响应大家对IDEA 12的支持,特奉上一个解决中文字体问题的好东东
- C#的GC,也就是垃圾回收机制 及其他
- JS中关于带操作赋值的一个小问题
- javascript(js)浮点数字精度问题的一个解决办法。
- Firefox - 附加软件 - Firebug - 其他问题 - 设置Javascript.options.strict为False避免Firebug出错
- “无法更新EntitySet“*****”,因为它有一个DefiningQuery,而元素中没有支持当前操作的元素”问题的解决方法
- .NET----使用母版页后,控件名称自动生成导致js无法正常操作.net控件的问题
- WCF热门问题编程示例(2)多个实例调用一个WCF服务操作,需要等待服务响应吗