垃圾回收
我们使用程序时,我们是在内存中运行的,当我们创建变量,函数的时候,他就会占用内存空间,我们不使用这些变量或者函数的时候我们就应该清除他,不然内存占用就会越来越大,最后直至内存崩溃
js的垃圾回收就是找出不会再使用的变量,释放其占用的内存空间\
标记清除(mark-and-sweep)
js中最常用的垃圾回收方式就是标记清除。当变量进入环境时,例如,在一个函数中声明一个变量,就将这个变量标记为"进入环境",从逻辑上讲,永远不能释放进入环境变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为"离开环境"
function test(){ var a = 10; //被标记"进入环境"
var b = "hello"; //被标记"进入环境" }
test(); //执行完毕后之后,a和b又被标记"离开环境",被回收
引用计数(reference counting)
引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1,如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含对这个值的引用的变量又取得了另外一个值,则这个值的引用次数减1,当这个值的引用次数为0时,则说明没有办法再访问这个值了,因此就可以将其占用的内存空间回收回来。
let aa = [] // 数组[]引用1次
let bb = aa // 数组引用2次
bb = null // 释放内存,引用还剩下1次,即变量aa的引用还存在
IE9以下还在使用引用计数,当对象循环引用时,引用次数无法标记为0,就会导致无法被回收。其他浏览器废弃使用;
js的内存泄漏
内存泄漏是应用程序过去使用,但不再需要的尚未返回到操作系统或可用内存池的内存片段。由于没有被释放而导致的,它将可能引起程序的卡顿和崩溃; 我们在chrome中可以看到内存的使用情况 检查-memory
意外的全局变量
一个未声明变量的引用会在全局对象中创建一个新的变量。在浏览器的环境下,全局对象就是window
function foo(arg) {
bar = "this is a hidden global variable";
}
dom泄漏
- 浏览器中DOM和js采用的是不一样的引擎,DOM采用的是渲染引擎,而js采用的是v8引擎,所以在用js操作DOM时会比较耗费性能,因为他们需要桥来链接他们。为了减少DOM的操作,我们一般将常用的DOM;
- 我们会采用变量引用的方式会将其缓存在当前环境。如果在进行一些删除、更新操作之后,可能会忘记释放已经缓存的DOM;
var elements = {
button: document.getElementById('button'),
image: document.getElementById('image')
};
function doStuff() {
elements.image.src = 'http://test.png';
}
function removeImage() {
// image 元素是body的直接子元素。
document.body.removeChild(document.getElementById('image'));
// 我们仍然可以在全局元素对象中引用button。换句话说,button元素仍在内存中,无法由GC收集
}
闭包
闭包可以使变量常驻内存,但如果使用不当就会在成内存泄漏
var theThing = null;
var replaceThing = function () {
var originalThing = theThing;
var unused = function () {
if (originalThing)
console.log("hi");
};
theThing = {
longStr: new Array(1000000).join('*'),
someMethod: function () {
console.log(someMessage);
}
};
};
setInterval(replaceThing, 1000);
定时器或者回调
var someResouce=getData();
setInterval(function(){
var node=document.getElementById('Node');
if(node){
node.innerHTML=JSON.stringify(someResouce)
}
},1000)