内存管理
像 C 语言这样的底层语言一般都有底层的内存管理接口,比如 malloc() 和free() 。相反,JavaScript是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。 释放的过程称为垃圾回收。这个“自动”是混乱的根源,并让JavaScript(和其他高级语言)开发者错误的感觉他们可以不关心内存管理。
因此可知 JavaScript 的内存管理使用的是 垃圾回收机制。
内存生命周期
不管什么程序语言,内存生命周期基本是一致的:
- 分配你所需要的内存
- 使用分配到的内存(读、写)
- 不需要时将其释放\归还
所有语言第二部分都是明确的。第一和第三部分在底层语言中是明确的,但在像JavaScript这些高级语言中,大部分都是隐含的。
内存的回收:
不再需要使用的变量也就是生命周期结束的变量,是局部变量,局部变量只在函数的执行过程中存在, 当函数运行结束,没有其他引用(闭包),那么该变量会被标记回收。
全局变量的生命周期直至浏览器卸载页面才会结束,也就是说全局变量不会被当成垃圾回收。
function fn() {
var a={name:'lisa'};
}
fn();//函数调用时才给局部变量 a 分配内存空间,函数执行完毕局部变量 a 自动释放其所占内存(释放的过程称为垃圾回收),而其值即引用的对象在没有其他变量对其引用时被垃圾回收器回收
上面例子中:
函数调用时才给局部变量 a 分配内存空间,函数执行完毕局部变量 a 自动释放其所占内存(释放的过程称为垃圾回收),而其值即引用的对象在没有其他变量对其引用时被垃圾回收器回收。
垃圾回收
垃圾回收算法主要依赖于 引用 的概念。在内存管理的环境中,一个对象如果有访问另一个对象的权限(隐式或者显式),叫做一个对象引用另一个对象。例如,一个Javascript对象具有对它原型的引用(隐式引用)和对它属性的引用(显式引用)。
在这里,“对象”的概念不仅特指 JavaScript 对象,还包括函数作用域(或者全局词法作用域)。
垃圾回收算法包括:
- 引用计数垃圾收集(最初级的垃圾收集算法),没有引用指向该对象(零引用),对象将被垃圾回收机制回收。
- 标记-清除算法: 这个算法假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象……从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。
从全局对象出发无法获取的对象,他们将会被垃圾回收器回收。
从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。
引用计数垃圾收集:
例子:
var o = {
a: {
b:2
}
};
// 两个对象被创建,一个作为另一个的属性被引用,另一个被分配给变量o
// 很显然,没有一个可以被垃圾收集
var o2 = o; // o2变量是第二个对“这个对象”的引用
o = 1; // 现在,“这个对象”只有一个o2变量的引用了,“这个对象”的原始引用o已经没有
var oa = o2.a; // 引用“这个对象”的a属性
// 现在,“这个对象”有两个引用了,一个是o2,一个是oa
o2 = "yo"; // 虽然最初的对象现在已经是零引用了,可以被垃圾回收了
// 但是它的属性a的对象还在被oa引用,所以还不能回收
oa = null; // a属性的那个对象现在也是零引用了
// 它可以被垃圾回收了
内存泄漏
有待总结学习,参考文章- 4类 JavaScript 内存泄漏及如何避免
参考文章: