JavaScript内存管理机制

JavaScript解释器的内存管理机制:当定义变量时为其分配一部分内存空间,当不再使用这个变量时就会自动释放这部分内存空间,即垃圾回收(garbage collection)。
这种机制使我们在进行开发时不用花太多时间考虑内存使用情况,可以按需定义变量。但是了解内存管理机制便于我们对JavaScript进行代码优化以及避免内存泄露。

一、内存分配

定义变量时,JavaScript自动为变量分配内存。

var num = 1;//为数值变量分配内存
var str = "test";//给字符串分配内存
var obj = {
a:1
};//为对象及其包含变量分配内存
function fun(arg){
    return arg;
}//为函数分配内存

是在声明时还是在赋值时分配的内存呢?我的理解是声明变量的同时分配了内存。犀牛书中指出

如果未在var声明语句中给变量指定初始值,那么虽然声明了这个变量,但在给它存入一个值之前,它的初始值就是undefined。

验证代码:

var a;
console.log(a === undefined);//true

那么声明变量时相当于同时将undefined赋值给它,那么其实应该在声明变量时为这个变量分配了内存空间。(若理解有误,还请指出)

二、垃圾回收(garbage collection)

垃圾回收就是释放不再使用的变量所占用的内存。JavaScript解释器中嵌入了“垃圾回收器”,用来跟踪内存的分配和使用情况,当分配的内存不再使用时,就自动释放这部分内存。
然而“不再使用”的标准是什么?如何判定?很难有明确的标准。
目前主要有引用计数法和可达性分析法两种判断方法,因此常用的垃圾清除的算法有:引用计数算法和标记清除算法(mark-and-sweep)。

  1. 引用计数算法
    引用是指一个对象对另一个对象的访问。
    引用计数算法的原理是:垃圾回收器定期扫描创建的对象,并计算这个对象被其他对象引用的个数,如果这个对象被引用的次数为0(没有其他对象引用改对象,可以通过赋值null或其他赋值的方式切取消引用),那么就释放这个对象占用的内存。
    MDN上这个代码很精确的描述了计数过程:
var o = {
  a:{
    b:2
  }
};//创建了两个对象,一个(之后称为obj2)被另一个(称obj1)
  //的属性a引用,obj1分配给变量o,被o引用,obj1引用次数都为1
var o2 = o;//o2是第二个对obj1的引用 obj1引用次数为2
o = 1;//o对obj1的引用被取消,obj1引用次数为1
var oa = o2.a;//引用obj1的a属性,即obj2,obj2,obj1引用次数都为1
o2 = "yo";//o2对obj1的引用被取消,
        //但是obj1的属性a的对象obj2还在被引用obj1还不能被回收
oa = null;//obj2的引用个数变为0,因此obj1可以被回收了

但是利用引用的方式存在一个严重的缺陷:循环引用导致内存泄露。当不需要一个对象时仍然存在就会导致内存泄露(改回收的没回收占用空间)。
当两个对像彼此引用且彼此保留时,就会产生循环,也就是这两个对象被引用次数不会为0。因此不会被回收。
IE6,IE7中一个常见的用法就存在循环引用情况

var div = document.createElement("div");
div.onclick = function(){
  doSomething();
}; // div有指向事件处理函数onclick的引用,同时onclick可以在函数
//作用域中访问div,对div进行引用

以上代码会导致两个对象都不会被回收,造成内存泄露。
一种解决方案是可以对两个对象赋值为null取消彼此间引用。

  1. 标记清除算法
    现在大部分浏览器都采用标记清除算法进行垃圾回收。这个算法依据对象是否可以获得的思路进行垃圾回收。垃圾回收器从全局对象开始扫描所有引用的对象以及这些对象引用的对象,可以获得的都是需要使用的,无法获得的就是需要回收的。
    这种方法能解决循环引用导致的内存泄露,只要其中的对象无法从全局对象扫描中获得就会回收内存。

三、JavaScript代码优化

  1. 尽量不使用全局变量
    之前自己在写一些不是通用的功能时,一直忧虑要不要将这块功能以及相应变量用函数包起来,全局变量默认情况下不会被回收,最好将变量定义在包装函数中。
  2. 匿名函数包装
    比如这样
(function() {

})();

(function(win, doc, $, undefined) {

})(window, document, jQuery);
  1. 通过null取消变量引用
    4.

参考文档

  1. Memory Management
  2. Memory leak patterns in JavaScript
  3. 【译】编写高性能JavaScript
  4. JavaScript也谈内存优化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值