对象内存javascript的内存管理

时间紧张,先记一笔,后续优化与完善。

    

绍介

    低层次的语言,如C,拥有级低别的内存管理令命,如:malloc()和free(),须要开发者手工释放内存。然而像javascript这样的高级语言情况则不同,对象(objects, strings 等)创立的时候分配内存,当他们不在用使的时候内存会被主动收回,这个主动收回的进程被称为渣滓收回。因为渣滓收回的存在,让javascript等高级语言开发者生产了一个错误的意识,认为可以不必心关内存管理。

 

    

内存生命周期

    不管什么样的编程语言,内存的生命周期基本上是致一的。

    

  1. 分配你须要的内存
  2. 用使他行进写读作操
  3. 当内存不须要的时候,释放资源

    骤步1和骤步2对于全部语言都一样,能显明觉察到。至于骤步3,级低别语言须要开发者显式行执。而对于像javascript这样的高级语言,这部份作操是交给解析器实现的,所以你不会觉察到。

 

    

javascript中的分配作操

    

值的初始化

    在为变量赋值的时候,javascript会实现内存的分配作工。

var n = 123; // 为数字分配内存
var s = "azerty"; // 为字符串分配内存
 
var o = {
  a: 1,
  b: null
}; // 为括包属性值的object对象分配内存
 
var a = [1, null, "abra"]; // 为括包值的数组分配内存
 
function f(a){
  return a + 2;
} // 为数函分配内存(数函是可调用的对象)
 
// 数函表达式一样也是对象,存在分配内存的情况
someElement.addEventListener('click', function(){
  someElement.style.backgroundColor = 'blue';
}, false);
通过数函调用实现分配

    一些数函当行执终了后之,一样存在对象分配的情况生发。

var d = new Date();
var e = document.createElement('div'); // 分配一个 DOM 素元
一些法方会分配新值或者对象。
var s = "azerty";
var s2 = s.substr(0, 3); // s2 是一个新的字符串
// 由于字符串是变不的,javascript会为[0, 3]范围的容内创立一个新的字符串
 
var a = ["ouais ouais", "nan nan"];
var a2 = ["generation", "nan nan"];
var a3 = a.concat(a2); // 把 a 和 a2 结合在一起,生产一个新的数组

    

对值的用使

    对值的用使,其实也就是对分配后的内存行执写读作操。这些作操括包:对变量或者对象的属性行进写读作操,或者向数函传递参数。

 

    

当不再须要的时候,释放内存

    绝大多数内存管理的问题都生发在这个阶段。最难做的情事是,如何判断分配的内存不再须要。这往往须要开发者做出判断,程序在什么时候不再须要内存,并释放他所占资源。

    高级语言的解析器中嵌入了一个叫做“渣滓集收器”的程序,他的作工是用来踪跟内存的分配和用使,判断内存是不是被须要,在不再须要的时候行执资源释放作操。他只能取得一个近似值,因为判断一个内存是不是被须要,这是个不确定的问题(不能通过一种算法决解)。

 

    

渣滓收回

    正如上文所述,我们没法确准的做到主动判断“内存不再须要”。所以,渣滓收回对该问题的决解方案有限局性。本节将解释必要的观点,懂得要主的渣滓集收算法和它们的限局性。

 

    

用引

    渣滓收回中一个要主的观点是用引。在内存管理中,当一个对象无论是显式的还是隐式的用使了另外一个对象,我们就说他用引了另外一个对象。例如,javascript对象存在一个隐式的向指原型的用引,还有显式向指他的属性值的用引。

    每日一道理
如果说友谊是一颗常青树,那么,浇灌它的必定是出自心田的清泉;如果说友谊是一朵开不败的鲜花,那么,照耀它的必定是从心中升起的太阳。 多少笑声都是友谊唤起的,多少眼泪都是友谊揩干的。友谊的港湾温情脉脉,友谊的清风灌满征帆。友谊不是感情的投资,它不须要股息和分红。(友谊可以换其他词语)

    在这里,对象的观点超出了javascript传统意义上对象的观点,他还括包数函作用域和全局作用域。

 

    

用使用引计数算法的渣滓收回

    上面要绍介的是一种最理想化的算法,引入了 “对象不再须要” 和 “没有其他对象用引该对象” 的观点。当该对象的用引指针为变0的时候,就认为他可以被收回。

    例子:

var o = { 
  a: {
    b:2
  }
}; // 创立了两个对象. 一个对象(a)被另外一个对象(o用引的对象)用引,并把a作为他的属性
// 该对象又被变量o用引
// 很显明,这时没有对象能被收回
 
 
var o2 = o; // 变量 o2 再次用引了该对象
o = 1; // o 不再用引该对象,只有o2还在用引该对象
 
var oa = o2.a; // oa用引 o2 的属性对象 a
// 该对象被其他两个对象用引,分别是o2的属性a和oa变量
 
o2 = "yo"; // 该对象经已不再被其他对象用引了,但是他的属性a任然被oa变量用引,所以他还不能被释放

oa = null; // 当初属性a也不再被别的对象用引,该对象可以被收回了
制限:环循

    该算法有其限局性,当一个对象用引另外一个对象,当成形环循用引时,即时他们不再被须要了,渣滓集收器也不会收回他们。

function f(){
  var o = {};
  var o2 = {};
  o.a = o2; // o 用引 o2
  o2.a = o; // o2 用引 o
 
  return "azerty";
}
 
f();
// 两个对象被创立,并成形互相用引
// 数函调用结束后之,他们不会离脱数函作用域,虽然他们不会被用使,但不会被释放
// 这是因为,用引计数的算法判断只要对象存在被用引的情况,那么就不能对其行执渣滓收回
实现中的例子

    ie6、7中,在dom对象上用使用引计数的算法,这里会存在内存泄漏的问题。

var div = document.createElement("div");
div.onclick = function(){
  doSomething();
}; // div 通过 click 属性用引了事件处理程序
// 当事件处理数函中拜访了div变量的时候,会成形环循用引,将致使两个对象都不会被收回,形成内存泄漏
 

    

标记 - 清除算法

    他引入了“对象不再须要”和“对象可不拜访(对象可不达)”的观点。该算法假设有一系列的根对象(javascript中的根对象就是全局对象),每隔一段时间,渣滓集收器就会从根对象开始,遍历所以他用引的对象,然后再遍历用引对象用引的对象,以此类推。用使种这式方,渣滓集收器可以取得全部可拜访的对象,收回那些可不拜访的对象。

    种这算法比之前的算法好些,0用引的对象会被设置为可不拜访对象,同时他也避免了环循用引形成的困恼。

    止截2012年,大多数代现浏览器用使的是种这“标记-清除算法”的渣滓收回器。JavaScript渣滓集收范畴(代/增量/并发/行并的渣滓集收),在去过的几年善改了与之相干的算法,但是渣滓集收算法本身(标记-清除算法)和“如何判断一个对象不再须要”并没有得以善改。

    

周期不再是一个问题

    在第一个例子中,数函调用结束后之,这两个对象不会被全局对象用引,也不会被全局对象用引的对象用引。因此,他们会被javascript渣滓收回器标记为可不拜访对象。种这情事一样也生发在第二个例子中,当div和事件处理数函被渣滓收回器标记为可不拜访,他们就会被释放掉。

    

制限:对象须要明白的标记为可不拜访

    种这标记的法方存在限局,但是我们在编程中被没有触接到他,所以我们很少心关渣滓收回相干的容内。

 

    原文地址:https://developer.mozilla.org/en-US/docs/JavaScript/Memory_Management

文章结束给大家分享下程序员的一些笑话语录: 乔布斯:怎么样还是咱安全吧!黑客:你的浏览器支持国内网银吗?苹果可以玩国内的网游吗乔布斯:......不可以黑客:那我研究你的漏洞干嘛,我也需要买奶粉!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值