JavaScript的内存释放问题详解


Posted in Javascript onJanuary 21, 2015

本文详细的讲解了JavaScript及IE浏览器对内存的管理和释放的时机和方法,希望对前端开发人员有所帮助。

一个内存释放的实例

<SCRIPT LANGUAGE="JavaScript">

<!--

strTest = "1";

for ( var i = 0; i < 25; i ++ )

{

strTest += strTest;

}

alert(strTest);

delete strTest;

CollectGarbage();

//-->

</SCRIPT>

CollectGarbage,是IE的一个特有属性,用于释放内存的,使用方法嘛应该是,将该变量或引用对象,设置为null或delete,然后在进行释放动作

在做CollectGarbage前,要必需清楚的两个必备条件:

引用- 一个对象在其生存的上下文环境之外,即会失效。
- 一个全局的对象在没有被执用(引用)的情况下,即会失效。

//---------------------------------------------------------

// JavaScript对象何时失效

//---------------------------------------------------------

function testObject() {

var _obj1 = new Object();

}

function testObject2() {

var _obj2 = new Object();

return _obj2;

}

// 示例1

testObject();

// 示例2

testObject2()

// 示例3

var obj3 = testObject2();

obj3 = null;

// 示例4

var obj4 = testObject2();

var arr = [obj4];

obj3 = null;

arr = [];

在这四个示例中:
- “示例1”在函数testObject()中构造了_obj1,但是在函数退出时,它就已经离开了函数的上下文环境,因此_obj1失效了;

- “示例2”中,testObject2()中也构造了一个对象_obj2并传出,因此对象有了“函数外”的上下文环境(和生存周期),然而由于函数的返回值没有被其它变量“持有”,因此_obj2也立即失效了;

- “示例3”中,testObject2()构造的_obj2被外部的变量obj3持用了,这时,直到“obj3=null”这行代码生效时,_obj2才会因为引用关系消失而失效。

- 与示例3相同的原因,“示例4”中的_obj2会在“arr=[]”这行代码之后才会失效。

但是,对象的“失效”并不等会“释放”。在JavaScript运行环境的内部,没有任何方式来确切地告诉用户“对象什么时候会释放”。这依赖于JavaScript的内存回收机制。——这种策略与.NET中的回收机制是类同的。

在前面的Excel操作示例代码中,对象的所有者,也就是"EXCEL.EXE"这个进程只能在“ActiveX Object实例的释放”之后才会发生。而文件的锁,以及操作系统的权限凭证是与进程相关的。因此如果对象仅是“失效”而不是“释放”,那么其它进程处理文件和引用操作系统的权限凭据时就会出问题。

——有些人说这是JavaScript或者COM机制的BUG。其实不是,这是OS、IE和JavaScript之间的一种复杂关系所导致的,而非独立的问题。

Microsoft公开了解决这种问题的策略:主动调用内存回收过程。

在(微软的)JScript中提供了一个CollectGarbage()过程(通常简称GC过程),GC过程用于清理当前IE中的“失效的对象失例”,也就是调用对象的析构过程。

在上例中调用GC过程的代码是:

//---------------------------------------------------------

// 处理ActiveX Object时,GC过程的标准调用方式

//---------------------------------------------------------

function writeXLS() {

//(略...)

excel.Quit();

excel = null;

setTimeout(CollectGarbage, 1);

}

第一行代码调用excel.Quit()方法来使得excel进程中止并退出,这时由于JavaScript环境执有excel对象实例,因此excel进程并不实际中止。

第二行代码使excel为null,以清除对象引用,从而使对象“失效”。然而由于对象仍旧在函数上下文环境中,因此如果直接调用GC过程,对象仍然不会被清理。

第三行代码使用setTimeout()来调用CollectGarbage函数,时间间隔设为'1',只是使得GC过程发生在writeXLS()函数执行完之后。这样excel对象就满足了“能被GC清理”的两个条件:没有引用和离开上下文环境。

GC过程的使用,在使用了ActiveX Object的JS环境中很有效。一些潜在的ActiveXObject包括XML、VML、OWC(Office Web Componet)、flash,甚至包括在JS中的VBArray。从这一点来看,ajax架构由于采用了XMLHTTP,并且同时要满足“不切换页面”的特性,因此在适当的时候主动调用GC过程,会得到更好的效率用UI体验。

事实上,即使使用GC过程,前面提到的excel问题仍然不会被完全解决。因为IE还缓存了权限凭据。使页的权限凭据被更新的唯一方法,只能是“切换到新的页面”,

因此事实上在前面提到的那个SPS项目中,我采用的方法并不是GC,而是下面这一段代码:

//---------------------------------------------------------

// 处理ActiveX Object时采用的页面切换代码

//---------------------------------------------------------

function writeXLS() {

//(略...)

excel.Quit();

excel = null;

// 下面代码用于解决IE call Excel的一个BUG, MSDN中提供的方法:

// setTimeout(CollectGarbage, 1);

// 由于不能清除(或同步)网页的受信任状态, 所以将导致SaveAs()等方法在

// 下次调用时无效.

location.reload();

}

delete 运算符在手册上的说明
引用从对象中删除一个属性,或从数组中删除一个元素。

delete expression

expression 参数是一个有效的 JScript 表达式,通常是一个属性名或数组元素。

说明

如果 expression 的结果是一个对象,且在 expression 中指定的属性存在,而该对象又不允许它被删除,则返回 false。

在所有其他情况下,返回 true。

最后之最后,关于GC的一个补充说明:在IE窗体被最小化时,IE将会主动调用一次CollectGarbage()函数。这使得IE窗口在最小化之后,内存占用会有明显改善

Javascript 相关文章推荐
jquery animate图片模向滑动示例代码
Jan 26 Javascript
使用基于jquery的gamequery插件做JS乒乓球游戏
Jul 31 Javascript
js 实现日期灵活格式化的小例子
Jul 14 Javascript
JS获取地址栏参数的几种方法小结
Feb 28 Javascript
JS将光标聚焦在文本最后的实现代码
Mar 28 Javascript
jQuery实现摸拟alert提示框
May 22 Javascript
KnockoutJS 3.X API 第四章之数据控制流if绑定和ifnot绑定
Oct 10 Javascript
JavaScript Drum Kit 指南(纯 JS 模拟敲鼓效果)
Jul 23 Javascript
JavaScript中错误正确处理方式小结你用对了吗
Oct 10 Javascript
JS实现的邮箱提示补全效果示例
Jan 30 Javascript
vue2中使用sass并配置全局的sass样式变量的方法
Sep 04 Javascript
vue单页应用在页面刷新时保留状态数据的方法
Sep 21 Javascript
script标签属性用type还是language
Jan 21 #Javascript
JS交换变量的方法
Jan 21 #Javascript
setinterval()与clearInterval()JS函数的调用方法
Jan 21 #Javascript
js实现DOM走马灯特效的方法
Jan 21 #Javascript
浅谈javascript 迭代方法
Jan 21 #Javascript
js实现用户注册协议倒计时的方法
Jan 21 #Javascript
浅谈javascript 归并方法
Jan 21 #Javascript
You might like
使用PHP json_decode可能遇到的坑与解决方法
2017/08/03 PHP
laravel高级的Join语法详解以及使用Join多个条件
2019/10/16 PHP
在IE6下发生Internet Explorer cannot open the Internet site错误
2010/06/21 Javascript
基于jquery的cookie的用法
2011/01/10 Javascript
js/html光标定位的实现代码
2013/09/23 Javascript
Jquery获取元素的父容器对象示例代码
2014/02/10 Javascript
JS实现一个列表中包含上移下移删除等功能
2014/09/24 Javascript
jQuery选择器源码解读(三):tokenize方法
2015/03/31 Javascript
jquery代码实现简单的随机图片瀑布流效果
2015/04/20 Javascript
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
2015/08/15 Javascript
浅谈EasyUI常用控件的禁用方法
2016/11/09 Javascript
Vue实现百度下拉提示搜索功能
2017/06/21 Javascript
关于Angularjs中自定义指令一些有价值的细节和技巧小结
2018/04/22 Javascript
jQuery内容过滤选择器与子元素过滤选择器用法实例分析
2019/02/20 jQuery
vue实现导航菜单和编辑文本的示例代码
2020/07/04 Javascript
原生js实现表格翻页和跳转
2020/09/29 Javascript
[01:02:47]EG vs Secret 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.21.mp4
2020/07/19 DOTA
python 域名分析工具实现代码
2009/07/15 Python
Python程序设计入门(2)变量类型简介
2014/06/16 Python
Python文件操作基本流程代码实例
2017/12/11 Python
Python简单读写Xls格式文档的方法示例
2018/08/17 Python
python按键按住不放持续响应的实例代码
2019/07/17 Python
Python使用matplotlib绘制Logistic曲线操作示例
2019/11/28 Python
使用opencv将视频帧转成图片输出
2019/12/10 Python
美国卡车、吉普车和SUV零件网站:4 Wheel Parts
2016/11/24 全球购物
魅力惠奢品线上平台:MEI.COM
2016/11/29 全球购物
Orvis官网:自1856年以来,优质服装、飞钓装备等
2018/12/17 全球购物
澳大利亚领先的武术用品和健身器材供应商:SMAI
2019/03/24 全球购物
酒店端午节促销方案
2014/02/18 职场文书
承租经营合作者协议书
2014/10/01 职场文书
社区务虚会发言材料
2014/10/20 职场文书
2015社区精神文明建设工作总结
2015/04/21 职场文书
元宵节晚会主持词
2015/07/01 职场文书
新教师教学工作总结
2015/08/12 职场文书
Python必备技巧之函数的使用详解
2022/04/04 Python
Java版 简易五子棋小游戏
2022/05/04 Java/Android