js 内存管理的知识,主要从三个方面来看。
- 内存分类
- 垃圾回收机制
- 内存泄漏相关
内存管理是每种编程语言的基本能力,区别是有的语言会开放 api,有的语言则不会,比如 js。js 是通过自己的垃圾回收机制
自动管理内存的
- 挖坑 — 分配内存
- 用坑 - 内存的读与写
- 还坑 = 内存释放
“坑” 也是不同的,分两种,下面介绍 👇
JS 中的数据类型有两类:基本类型
和引用类型
。
基本类型包括:String、Number、Boolean、null、undefined、Symbol,存储于栈内存
引用类型包括:Object、Array、Function,Date,存储于堆内存
堆和栈分别是不同的数据结构。栈是线性表的一种,而堆则是树形结构。
在访问 a、b、c 三个变量时,从栈中直接获取该变量的值;
访问 d 和 e 时,需要分两步走:
- 从栈中获取变量对应值的引用(堆内存中的地址)
- 用上一步获取到的引用,再去堆内存找到数据
垃圾回收是指,当一个变量不再被需要之后,自动释放掉所占用的内存空间
判断依据 - 垃圾回收算法!
下面介绍两种算法 👇
引用:一个对象如果有权访问另一个对象(隐式或者显式),就叫做引用另一个对象。例如,一个 Javascript 对象具有对它原型的引用(隐式引用)和对它属性的引用(显式引用)
谁能访问,谁引用
声明一个变量等于创建一个引用。
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值就加 1;当引用失效时,计数器值就减 1;
当引用为 0 时,变量所占用的内存空间会被释放掉;
引用计数法已被现代浏览器淘汰,原因之一是在循环引用下,引用永远无法为 0,内存不会释放,容易造成内存泄漏
var cycleObj1 = {};
var cycleObj2 = {};
cycleObj1.target = cycleObj2;
cycleObj2.target = cycleObj1;
该算法的判断标准,是变量是否可抵达
!
两个阶段:
- 标记阶段:从根对象(Window 或 Global)开始扫描,可用变量标记为
可抵达
- 清除阶段:发现没有被标记为 “可抵达” 的变量,一键清除
内存泄漏:不使用的变量(内存垃圾)没有被释放,导致内存占用攀升
非严格模式下,me 而非 var me 这种写法,会使 me 挂载到全局
function test() {
me = "xiuyan";
}
setInterval 和 setTimeout 链式调用,未清除的话,会导致内存泄漏
setInterval(function () {
// 函数体
}, 1000);
setTimeout(function () {
// 函数体
setTimeout(arguments.callee, 1000);
}, 1000);