废话片:
讲到内存可以联想到很多,内存分配管理,内存回收机制,内存泄露等等,今天我们就来答题的总结一下。
正文片:
1.内存分配管理
2.内存回收机制
3.内存泄露
一、内存分配管理
首先让我们看看内存的分配机制吧。其实在所有的语言中内存的分配都是一样的,首先在我们需要的时候记性内存的分配,然后是使用分配的内存,最后是当我们不适用的时候收回内存块。
问题:在js中是如何分配内存的呢,什么时候分配呢?
回答:在js中当我们定义了变量的时候实际上就为我们分配好了内存的,这样将会省去我们的很多麻烦。了如如下:
1 // 给数值变量分配内存 2 var n = 123; 3 // 给字符串分配内存 4 var s = "azerty"; 5 6 // 给对象及其包含的值分配内存 7 var o = { 8 a: 1, 9 b: null 10 }; 11 12 // 给数组及其包含的值分配内存(就像对象一样) 13 var a = [1, null, "abra"]; 14 15 // 给函数(可调用的对象)分配内存 16 function f(a){ 17 return a + 2; 18 } 19 20 // 函数表达式也能分配一个对象 21 someElement.addEventListener('click', function(){ 22 someElement.style.backgroundColor = 'blue'; 23 }, false);
当然,还有其他的也写情况实际上也是需要系统为我们分配内存的,例如当我们使用构造函数来定义一个新的对象的时候,我们是需要对新的对象讨要空间的。
1 var d = new Date(); // 分配一个 Date 对象 2 var e = document.createElement('div'); // 分配一个 DOM 元素
有的时候我们需要对于数据进行组合或是在原有的数据上进行值的设置,这时系统也会为我们新分配一块内存区域。
1 var s = "azerty"; 2 var s2 = s.substr(0, 3); // s2 是一个新的字符串 3 // 因为字符串是不变量 4 // JavaScript 可能没有分配内存 5 // 但只是存储了 [0-3] 的范围。 6 7 var a = ["ouais ouais", "nan nan"]; 8 var a2 = ["generation", "nan nan"]; 9 var a3 = a.concat(a2); 10 // 新数组有四个元素,是 a 连接 a2 的结果
问题:内存空间使用?
回答:当系统为我们分配了内存空间之后我们实际上在每一次对于当前的值得操作的时候都是使用了这一内存块,读取和写入操作将会是我们对于内存块的基础操作。
二、内存回收机制
问题:js的内存是如何回收的?
回答:js是具有自动垃圾收集机制的,这种机制会自动的跟踪每一个变量的动向,并判断当前的变量是否还有存在的必要,然后将不必要的变量所占用的内存进行收回。对于这样的收回机制,实际真正的运用起来是有两种不同的方法来实现的。详情见如下:
1.方法一:标记清除算法
这一算法是为进入环境中的变量标记一个“进入环境”的标记。逻辑上讲呢,当我们的变量进入环境的时,变量实际上是不应该被删除的,因为上下文中可能会用到当前的变量进行相关的逻辑演算,而当变量离开环境的时候,竟会为其标记成为“离开环境”的状态。
2.方法二:引用计数
引用对象是放在堆中的,而这一内存清理方法是对这一值的引用次数进行统计,当我们声明了一个变量,并且将引用对象的值赋值给了这一变量,则引用对象的引用计数加 一,反之当我们的引用对象的相关引用变量其指向的内容发生了变化,则引用对象的引用计数减一。当引用对象的引用计数为0的时候这表明,此对象值可回收。
以上其实就是最为常用的内存回收机制,当然我们的内存回收机制是在一定的时间间隔后,自动的运行的,每次都会搜寻是否有变量可以收回,并回收内存。
三、内存泄漏
内存泄漏是指在我们编码的过程中,有的某一些操作是的当前的内存块即使不在会被使用到,释放机制也因为辨别不出(bug啦)是否需要释放而使得这一不需要的变量得以保留。虽然对于有内存回收机制的js和java是很少有这种情况发生的。但是。。。你懂得,下面就来看一看有哪些情况会导致这一情况
1、当我们在IE中使用.onclick的时候如果我们没有手动的删除这一事件则会造成和内存泄漏(IE果然好坑啊)
1 document.getElementById("xxx").onclick = fuction(){}; 2 //在IE中是不会自动的回收内存的。 3 4 //改进方法 5 document.getElementById("xxx").onclick = fuction(){ 6 document.getElementById("xxx").onclick = null; 7 ....... 8 }; 9 10 //或者使用 11 document.getElementById("xxx").addEventListener(......);
2、当我们对于DOM对象使用循环引用的情况下,js的回收机制就没有办法回收了。
1 var a = document.getElementById("xxx"); 2 a.r = a;
3、必报在编写过程中的时候是经常要使用到的一个概念。但是但我们在闭包中定义了响应时间的时候就会造成一定量的内存占用。
1 function bindEvent() 2 { 3 var obj=document.createElement("XXX"); 4 obj.onclick=function(){ 5 //Even if it's a empty function 6 } 7 }//这样闭包内的obj元素回因为其中的onclick时间的绑定而没有办法进行释放,这样就造成了运行时的内存浪费。
4、某些代码不严谨可能导致内存泄漏
1 a = {p: {x: 1}}; 2 b = a.p; 3 delete a.p;//a中的元素实际上已已经删除了,可是被删除的元素并没有清空,因为外部中变量b指向了这一元素数据。这样就可能造成内存的浪费
5、最后,我们在来黑IE一把,实际上在IE中有一些DOM操作或者是属性转化的操作会造成相关的内存泄漏的风险,所以说我们在编写适配IE浏览器的时候还是要更为的注意一些的啊。
内存泄漏的情况绝对不仅仅是我上面说的着一些,在我们的平时编写代码的过程中我们可以找到更多的这样的bug并对其进行相关的优化,将会使得我们的代码更为的良好而健壮。