首页 > 网站开发 > JavaScript >
-
垃圾回收机制
JavaScript是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。 释放的过程称为垃圾回收。这个“自动”是混乱的根源,并让JavaScript开发者错误的感觉他们可以不关心内存管理。
内存生命周期
不管什么程序语言,内存生命周期基本是一致的:
- 分配你所需要的内存
- 使用分配到的内存(读、写)
- 不需要时将其释放\归还
所有语言第二部分都是明确的。第一和第三部分在底层语言中是明确的,但在像JavaScript这些高级语言中,大部分都是隐含的。
js内存分配(值的初始化)
为了不让程序员费心分配内存,JavaScript 在定义变量时就完成了内存分配。
var n = 123; // 给数值变量分配内存
var s = "azerty"; // 给字符串分配内存
var o = {
a: 1,
b: null
}; // 给对象及其包含的值分配内存
// 给数组及其包含的值分配内存(就像对象一样)
var a = [1, null, "abra"];
function f(a){
return a + 2;
} // 给函数(可调用的对象)分配内存
// 函数表达式也能分配一个对象
someElement.addEventListener('click', function(){
someElement.style.backgroundColor = 'blue';
}, false)
使用值
使用值的过程实际上是对分配内存进行读取与写入的操作。读取与写入可能是写入一个变量或者一个对象的属性值,甚至传递函数的参数。
释放内存
大多数内存管理的问题都在这个阶段。在这里最艰难的任务是找到“哪些被分配的内存确实已经不再需要了”。它往往要求开发人员来确定在程序中哪一块内存不再需要并且释放它。高级语言解释器嵌入了“垃圾回收器”,它的主要工作是跟踪内存的分配和使用,以便当分配的内存不再使用时,自动释放它。
垃圾回收
垃圾回收机制分为两种:
- 引用计数法: 这是最初级的垃圾收集算法。此算法把“对象是否不再需要”简化定义为“对象有没有其他对象引用到它”。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。也就是说当前内存被占用一次,计数累加一次,移除占用就减1,减到0时,浏览器就回收它。
- 标记清除: 这个算法把“对象是否不再需要”简化定义为“对象是否可以获得”。最常用的垃圾回收机制就是标记清除,当变量进入执行环境时,被标记为'进入环境',当变量离开执行环境时,被标记为'离开环境'。某一个时刻,垃圾回收器会过滤掉环境中的变量,以及被环境变量引用的变量,剩下的就是被视为准备回收的变量。
开发过程中遇到的内存泄漏情况:
内存泄露是指当一块内存不再被应用程序使用的时候,由于某种原因,这块内存没有返还给操作系统或者内存池的现象,内存泄漏可能会导致应用程序卡顿或者崩溃。
在js中,常见的内存泄漏主要有5种
-
意外的全局变量
在非严格模式中,未定义的变量会被自动绑定到全局对象上(window/global),比如:
function foo() {
bar= 'somthing...'
}
foo()
函数内部变量没有定义,自动绑定到全局对象,就相当于 window.bar = 'somthing...',全局变量不会被回收,函数执行完,变量就一直还在内存中没有被释放。
解决方法: 使用严格模式或者在变量使用完毕后设置为 null,以回收内存。
2. 闭包
function foo() {
let a = 1 // 外部访问不到这个变量
function bar() {
return a // 这里将变量返回出去
}
return bar() // return出来后就给window了所以一直存在内存中。因为一直在内存中,在IE里容易造成内存泄漏
}
foo()
原因:闭包可以维持函数内局部变量,使其得不到释放。
解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。
3. 没有清理的DOM元素引用
原因:dom元素移除,但对dom元素的引用没有解除,会导致内存泄漏。
解决:手动删除。
4. 被遗忘的定时器或者回调
原因:当不需要setInterval或者setTimeout时,定时器没有被clear,定时器的回调函数以及内部依赖的变量都不能被回收,造成内存泄漏。
解决:比如:vue使用了定时器,需要在beforeDestroy 中做对应销毁处理。js也是一样的
5. 子元素存在引用引起的内存泄漏
原因:div中的ul li 得到这个div,会间接引用某个得到的li,那么此时因为div间接引用li,即使li被清空,也还是在内存中,并且只要li不被删除,他的父元素都不会被删除。
解决:手动删除清空。
原文:https://www.cnblogs.com/zyp-beier/p/15612684.html