内存管理
接上次的作用域和闭包,结合闭包聊js内存管理机制
js内存管理 垃圾回收机制 内存泄漏
js自身会完成内存回收这个功能,不用开发者处理
js的内存生命周期,分成三个阶段
- 分配内存
- 内存的读和写
- 内存的释放
在内存分配的阶段,会根据不同变量的类型,去确定具体放在生命地方。
比如可分为栈内存和堆内存
js中的数据类型分成:基本类型和引用类型
- 基本类型: number string boolean null undefined symbol bigint
大小固定,体积轻量,相对简单,它们被放在js的栈内存中
- 引用类型: object array functuin 这类数据类型都比较复杂
占用空间大,且大小不定,它们被放在js的堆内存中存储
栈和堆是不同的数据结构,栈是线性表的一种,而堆是树形结构
let a = 0;
let b = 'jing';
let c = null;
let d = {name:'jing'};
let e = ['jing']
在访问a,b,c三个变量时,直接从栈中获取该变量的值
在访问d,e时:
- 从栈中获取变量对应对象的引用(它堆内存中的地址)
- 拿这个地址去堆内存中查询,才能拿到我们想要的数据
垃圾回收机制 + 垃圾回收算法
当一个变量被判断成不再被需要使用了,垃圾回收器就会把这个变量占用的内存空间给释放掉,这个过程叫作垃圾回收。
那么js如何判断那个变量是不再需要使用了呢?
垃圾回收算法有两种-引用计数和标记清除
1. 引用计数 (最初的,现在的浏览器已经不用啦)
【只描述引用类型的内存地址】
const student = ['jing','hao'];
赋值表达式从右开始往左读
这行代码首先开辟了一快内存,把右侧的数组塞进去,此时的数组就占据了一块内存,随后student变量指向了它,这就是创建了一个指向该数组的引用,此时数组的引用计数就是1
引用计数的机制下,内存中的每个值都会对应一个引用计数,当垃圾收集器感知到某个值得引用计数为0时,就判断它没有用了,这个内存就会被释放
引用计数的弊端:
function jing() {
var obj1 = {};
var obj2 = {};
obj1.jing = obj2;
obj2.jing = obj1;
}
jing();
无法判断对象的循环引用,内存泄漏严重
2. 标记清除法 (现代浏览器标注垃圾回收算法)
在标记清除算法中,一个变量是否被需要的判断标准,是它是否可抵达
这个算法有两个阶段-标记阶段,清除阶段
- 标记阶段
- 垃圾收集器会先找到根对象,仔浏览器里面window 仔node里面 global
- 从根对象触发,垃圾收集器会扫描所有可以通过根对象触及的变量,这些对象会被标记成‘可抵达’
- 清除阶段
没有被标记为“可抵达”的变量,就会被认为是不需要的变量,这波变量会被清除
来看看标记清除模式下的下面这段代码如何进行垃圾回收
function jing() {
var obj1 = {};
var obj2 = {};
obj1.jing = obj2;
obj2.jing = obj1;
}
jing();
闭包和内存泄漏
- 导致的全局变量
function test() {
me = 'jing
}
- 忘记清除的setInterval 和 setTimeout
setInterval (fucntion() {
},1000)
setTimeout(function() {
setTimeout(arguments.callee,1000)
},1000)
使用定时器的时候,要记得清除
- 清除不当的DOM
const myDiv = document.getElementById('mydDiv')
function handele() {
// 一些与myDiv的逻辑
}
// 使用myDiv
handele()
// 尝试删除myDiv
document.body.removeChild(document.getElementById('myDiv'))
这个dom依旧存在,因为它依旧被使用
1139

被折叠的 条评论
为什么被折叠?



