Javascript has an automatic garbage collection mechanism, that is, the execution environment is responsible for managing the memory used in the execution of the code.In C and C++ languages, a basic task of developers is to track the usage of memory manually, which is a source of many problems.When writing Javascript programs, developers do not need to care about memory usage anymore, and the allocation of needed memory and useless recycling completely achieve automatic management.The principle of this garbage collection mechanism is very simple: find out the variables that are no longer used, and then release the memory that is occupied.To this end, the garbage collector performs the operation periodically according to a fixed time interval(或代码执行中的预定收集时间)。

我们需要在一个函数的局部变量的正常生命周期分析。只有在函数执行过程中存在的局部变量。在这个过程中,相应的空间是分配在栈内存中的局部变量(或堆)来存储他们的价值观,变数是在函数使用到执行的功能。在这一点上,局部变量是没有必要的,所以他们可以释放内存以供将来使用。在这种情况下,很容易判断变量是否仍然是必要的;但并不是在所有的情况下,很容易得出一个结论,垃圾收集器必须跟踪哪些变量是有用的和无用的变量,标记不再有用,变量恢复他们在未来占据的内存。用于识别无用变量的策略可能与实际情况不同,但在浏览器中的实现通常是两种策略。

马克清除

在Javascript中最常用的垃圾收集mark-and-sweep.when变量进入环境(例如,声明函数中的变量),变量是标记为入口环境。从逻辑上讲,你不能释放进入环境的变量的内存,因为它们可能被用来作为长期执行的流入相应的环境流。当一个变量叶片的环境中,它被标记为离开环境。

你可以用任何方式来标记变量。例如,我们可以翻转一个特殊的点来记录当一个变量进入环境,或使用一个变量列表进入环境变量列表,离开环境跟踪哪些变量发生了变化,如何标记变量是不是真的很重要,和所采取的策略是关键。

垃圾收集器运行时,它所有的变量存储在内存中添加标签(当然,它可以用任何方式)。然后,它会去除环境中的变量和环境变量的引用的变量后,对标签添加的变量将被考虑一个变量可以被删除,因为在环境变量已经无法访问这些变量。最后,垃圾收集器完成记忆清除,摧毁那些标记值和内存空间,他们占据回收。

到2008,IE、Firefox、Opera、Chrome和Safari的Javascript实现被垃圾收集策略(或类似策略)标记,但是垃圾回收间隔不同。

引用计数

另一个不常见的垃圾收集策略称为引用计数。引用计数的意义是跟踪次数每个价值参考。当一个变量被声明和引用类型的值赋给变量,对价值的参考人数是1。如果同一个值是给另一个变量的值,参考人数增加了1。相反,如果一个变量被添加到了另一个值,该值由1降低。当值的值被更改为0时,这意味着无法访问此值,因此可以恢复占用的内存空间。因此当垃圾收集器再次运行时,它释放引用值为零的值所占用的内存。

Netscape导航器3是第一个使用引用计数策略的浏览器,但它很快就遇到了一个严重的问题:循环引用。循环引用是指包含对对象B的引用的对象A,而对象B也包含对对象A的引用。

请看下面的例子。
复制代码代码如下所示:
函数(){
var对象=新的对象();
无功objectb =新的对象();

objecta.someotherobject = objectb;
objectb.anotherobject =对象;
}

在这个例子中,对象和objectb称对方通过各自的特性,即对这两个对象的引用数为2。在一个标记的清除策略的实施,这两个物体离开范围后执行功能。所以这两种相互引用是没有问题的。但是在引用计数策略的实施,对象和objectb是否会继续执行的功能是存在的,所以引用次数将永远是0。如果这个函数被调用多次,很多记忆不会恢复。因此,Netscape Navigator 4参考了在柜台的方式和使用标签清洗执行垃圾收集机制。然而,麻烦的C引起的引用计数没有终止。

我们知道,在IE中的一些对象不是本地Javascript对象。例如,在BOM和DOM对象是由C++的COM组件的形式实现(Component Object Model,组件对象模型),而COM对象的垃圾收集机制采用引用计数策略。因此,即使IE浏览器的Javascript引擎使用标记清晰的战略实施,COM对象,Javascript访问仍然是基于引用计数的策略。换句话说,只要COM对象是伊江设计的,会有一个循环引用问题。

下面的例子显示了一个循环引用问题从COM对象的使用而产生的:
复制代码代码如下所示:
VaR元= document.getelementbyid(some_element );
VaR MyObject =新的对象();
myobject.element =元;
element.somobject = MyObject;

此示例创建一个DOM元素之间的循环引用(元)和本地Javascript对象(MyObject)。在这种情况下,可变MyObject有一个属性命名元素指向该元素的对象;和可变元素有一个属性叫做someobject照应MyObject。由于这种循环引用,即使在这个例子DOM是从页面上删除,它永远不会被回收。

为了避免这种循环引用问题,最好在未使用它们时手动断开本地Javascript对象和DOM元素之间的连接:
复制代码代码如下所示:
myobject.element = null;
element.somobject = null;

将变量设置为NULL意味着切断变量和它先前引用的值之间的连接。但下次垃圾收集器运行时,它删除这些值并回收它们占用的内存。

性能问题

垃圾收集器运行周期,如果分配给该变量的内存量是目的,恢复工作也相当大。在这种情况下,它是确定垃圾收集的时间间隔的一个非常重要的问题。说到多久垃圾收集器运行一次,它不能帮助,但对即即垃圾收集器运行在内存分配的基础上,让人想起声名狼藉的性能。具体地说,它是256个变量,4096个对象(或数组),文字和数组元素(槽)或64Kb的字符串。以上的临界值,垃圾回收器将运行。实现的问题是,如果一个脚本包含太多的变量,它可能会保持其生活的变数。这样,垃圾收集器可能经常跑。结果,由此产生的初始IE7重写的垃圾收集程序。

随着IE7的发布,其Javascript引擎的垃圾收集例程改变了工作方式:可变分配触发垃圾收集,文字和/或数组元素的临界值调整为动态修正。在IE7的临界值都等于在初始化的IE6。如果分配给程序内存量小于15%时,该变量的临界值,文字和/或数组元素将翻倍。如果常规回收85%的内存分配,各种关键的复位将违约。这看似简单的调整,大大提高了IE的性能运行页面包含大量的Javascript时。

事实上,垃圾收集过程可以在一些浏览器触发,当我们不建议读者这样做。在伊江,叫window.collectgarbage()方法会立即指出垃圾收集。在opera7和后来的版本,称widnow.opera.collect()也将启动垃圾收集例程。

内存管理

使垃圾收集机制的编程语言,开发人员通常不需要担心内存管理。然而,在内存管理和垃圾收集的Javascript所面临的问题还是有点不同。最重要的问题之一是可用内存分配给Web浏览器的数量通常小于分配到桌面应用程序,这样做的目的是被认为是安全的,其目的是防止Javascript的页面的运行从整个系统的内存,导致系统崩溃。内存的限制不仅影响内存变量的配置,但也调用堆栈和报表,可以被执行的数量在同一时间在一个线程。

因此,为了确保最低内存可以让页面获得更好的性能,最好是通过设置它的值为null的释放的借鉴——这就是所谓的引用。这种方法用于大多数全球和全局对象的属性。局部变量自动解引用时,执行环境,如下面的示例所示:
复制代码代码如下所示:
功能createperson(name){
无功localperson =新的对象();
localperson.name =名称;
返回localperson;
};
无功gllbalperson = createperson(尼古拉斯);

globalperson参考手册/电梯
globalperson = null;

在这个例子中,变量globalperson已经createperson()函数返回一个值。在createperson()函数,我们创建一个对象并将它赋给局部变量localperson,然后添加一个名为name的属性的对象。最后,调用这个函数的时候,localperson函数返回分配给全局变量globalperson。因为在createperson的localperson()的执行完成后离开执行环境的功能,所以没有必要为他给我们引用。但对于全局变量globalperson,那么我们需要把它在不使用时手动释放它,这是最后一行代码在上面的例子中,目标。

但是,从引用值并不意味着内存的自动恢复值。提升引用的真正效果是让执行环境中的值,而垃圾收集器下一步运行恢复。

内存泄漏

因为即使用不同的垃圾收集例程Jscript对象和COM对象,在IE关闭引起的一些特殊问题。特别是,如果一个HTML元素保存在一个封闭的链条,这意味着该元素不能被破坏。看下面的例子:
复制代码代码如下所示:
功能assignhandler(){
VaR元= document.getelementbyid(someelement );
element.onclick =函数(){
警报(元。ID);
};
};

上面的代码创建一个闭包作为元素的时间处理程序和关闭造成循环引用。因为匿名函数保留指assignhandler主动对象(),它导致的参考,不能减少元件数量。只要匿名函数的存在,引用的元素的数量至少是1,那么它所占用的内存不会被回收。但是,这个问题可以通过一个小的重写代码解决,如下图所示:
复制代码代码如下所示:
功能assignhandler(){
VaR元= document.getelementbyid(someelement );
var id = element.id;

element.onclick =函数(){
警报(id);
};

元素= null;
};

在上面的代码中,一个副本的element.id是保存在一个变量,而变量引用封闭消除循环引用。但仅这一步不能解决内存泄漏的问题。必须记住,关闭将含有功能活动整个活动对象,其中包含元素。即使关闭不直接引用元素,参考仍将保存在包含函数的活动对象。因此,有必要设置变量为空。这样,对DOM对象的引用可以解除,和参考文献的数量减少的顺利确保它占用的内存通常是恢复。

解释

1,如果在另一个窗口中保留对象在窗口中的引用,即使窗口已关闭,内存也没有释放;

2,更糟的是,如果您保留的是DOM对象引用,关闭对象所在的窗口,IE将崩溃,报告内存错误(或需要重新启动)。