js垃圾回收机制
1.引用计数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="box">×</div>
<script>
// var box = document.getElementById('box');
// box.onclick = function() {
// this.remove();
// }
function demo() {
var a = 10;
console.log(a);
}
// JS中两种垃圾回收机制:引用计数、 标记清除
// 引用计数
// var a = {}; // 该内存的引用计数为1
// var b = a; // 该内存的引用计数为2
// var c = a; // 该内存的引用计数为3
// c = 1; // c变量保存数字1 不能再保存地址 所以原地址的引用计数由3 变为2
// b = 1; // b变量保存数字1 不能再保存地址 所以原地址的引用计数由2 变为1
// a = 1; // a变量保存数字1 不能再保存地址 所以原地址的引用计数由1 变为0
// 此时 原对象的地址已经不再被任何地方引用 所以无用 被视作“垃圾” 需要被回收
// 当垃圾回收机制启动的时候 会依次检查内存地址的这个数字 如果是0 会被回收掉
// 如果不是0 说明还依旧被引用 就不会被回收
// 但是引用计数 有一个问题 无法解决循环引用
// var a = {}
// var b = {};
// a.hello = b; // 给a添加了一个属性 hello 它的值 是b的地址
// b.hello = a;
// // b a.hello 这两种方式都可以访问到b对象 所以引用计数为2
// b = 1; // b 不再保存对象所以原b的对象的计数 -1 但是此时依旧可以通过a.hello去访问
// a = 1; // a 不再保存对象所以原a的对象的计数 -1 但是此时b的对象的地址依旧保存在a对象的属性上
// 所以原a的对象和原b的对象 各有一个属性指向对象
// 这种情况叫做内存泄漏
// 内存泄露:不能再被重新分配的内存 但是又访问不到
// 委托模式: 1 减少事件数量 2 动态创建的元素也有事件 3 防止内存泄漏
</script>
</body>
</html>
2.标记清除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id='box'>我是一个box</div>
<script>
// 标记清除的思路:从两个根(全局、DOM树)出发
// 只要能够沿着这两个根,找得到这个内存,就认为是有用 就不会被清除
// 1 让dom变量保存对象的地址
// var dom = {};
// 2 定义了一个新的对象 让这个对象也保存上一个对象的地址
// var bom = {
// dom: dom
// }
// 3 dom不再保存对象 但是此时 从bom也可以访问到那个被保存的对象
// dom = 1;
// 4 此时bom这个对象也不再保存原对象 此时 原对象就不能再被访问 所以就会丢失标记 当垃圾回收机制启动的时候就会把它给回收
// bom.dom = 1;
// 获取元素 此时 元素本来在dom树上 是占着内存的 这条语句只是多一个引用而已
// var dom = document.getElementById("box");
// dom.onclick = function() {
// console.log(1)
// }
// dom = null;
</script>
</body>
</html>