你没有看错!JavaScript是使用垃圾回收的语言,就是在执行环境中代码执行时管理内存。跟Java有一些相似。Java代码执行需要通过Java虚拟机,Java虚拟机可以帮助开发者管理内存。JavaScript通过自动内存管理实现内存分配和闲置资源回收。基本思想:确定哪个变量不会在使用,然后释放它占用的内存。例如页面跳转后,之前页面的变量占用着内存都会被释放掉其内存。在游览器发展史上,用到两种主要的内存清理策略:标记清理和引用计数,听起来跟Java虚拟机管理内存算法有些相似。那我们就开始了解这两个策略
标记清理
把每个变量添加上标记,例如:在函数内部声明一个变量时会加上存在于上下文标记,当变量离开上下文时,加上离开上下文标记。标记过程的实现并不重要,关键是策略。
在垃圾回收程序运行时,会标记内存中储存的所有变量,它会将所有在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉,在此之后再被加上标记的变量就是待删除的,原因是任何在上下文中的变量都访问不到它们了。之后垃圾回收程序做一次内存清理,摧毁带标记的所有值,回收他们的内存
引用计数
对每个值都记录它被引用的次数。声明变量并给它赋一个引用值时,引用数为1。如果同一个值又赋值给另一个变量,引用数加1。如果别的值赋值给刚才的值引用的变量,引用数减1。如果引用数为0时,垃圾回收程序下次运行的时候就会释放引用数为0的值的内存。这个策略不是太常用的,因为存在一个缺陷两个对象互相引用,这个对象就会一直存在,内存得不到释放
function problem() {
let objectA = new Object();
let objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
}
性能
垃圾回收程序会周期运行,如果内存中分配太多的变量,性能可能会损失,因为开发者不知道什么时候运行时会垃圾回收。尽量在代码上优化不能频繁创建无用变量,代码尽量简洁,组件化,使用封装函数,简化代码
内存优化
1.解除引用
优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。如果数据不再必要,那么把它设置为 null,等待内存被回收。虽然设置null不会立即内存被回收,但是该值已经不在上下文里了,下次垃圾回收肯定会被回收
function createPerson(name){
let localPerson = new Object();
localPerson.name = name;
return localPerson;
}
let globalPerson = createPerson("Nicholas");
// 解除 globalPerson 对值的引用
globalPerson = null;
2.通过 const 和 let 声明提升性能
const 和 let 的作用域都是块,与var相比较,会更早让垃圾回收,释放内存
3.隐藏类和删除操作
隐藏类是 利用构造函数 共享该函数内的属性。删除操作直接用delete关键字,删除变量。
4.避免内存泄漏
内存泄漏是在内存有限的设备上,或者函数会被调用很多次的情况下,分配的内存不够用,造成内存泄漏。
在定义变量需要有关键字声明,如果没有的话,这个变量就认为是window本身是不会释放内存。
在设置定时器时,定时器的回调通过闭包引用了外部变量,那么外部变量一直占用内存
闭包 中函数内部调用函数使得外部变量一直被引用,无法释放内存