唯心主义蠢货的[js知识总结] 事件处理和垃圾回收机制

事件处理和垃圾回收机制

事件处理机制

过程分析

JavaScript是单线程执行的,现在推行的多线程执行,都可以理解成伪多线程,事件循环是实现异步的机制

在这里插入图片描述

更具体来讲:

js的事件大体可以分为两种,Macrotask宏任务,Microtask微任务,循环机制为先执行宏任务,一个宏任务结束后执行内部对应的微任务,然后再执行下一个宏任务

Macrotask: script(整体代码),setTimeout, setInterval, setImmediate, I/O, UI rendering

Microtask:process.nextTick, Promises, Object.observe, MutationObserver

在这里插入图片描述

在现在浏览器中可能使用到就script(整体代码),setTimeout,setInterval,UI rendering,promise等,nodejs可能会用到其他的。

题目示例

下面来看一个题目理解一下:

console.log('start');
setTimeout(()=>{
    console.log('A');
},0);
console.log('end');

// start
// end
// A

先执行主代码块,即先执行start输出语句,然后将settimeout压入宏任务执行队列,再执行end输出语句,再执行宏任务执行队列输出A

进阶题目

1.
setTimeout(()=>{
    console.log('A');
},0);
var obj={
    func:function () {
        setTimeout(function () {
            console.log('B')
        },0);
        return new Promise(function (resolve) {
            console.log('C');
            resolve();
        })
    }
};
obj.func().then(function () {
    console.log('D')
});
console.log('E');

分析题目:

  1. 将第一行语句压入settimeout执行队列。
  2. 调用func()时,将console.log(‘B’)所在函数压入settimeout执行队列
  3. 返回promise,promise的exector函数执行console.log(‘C’),输出C
  4. 将.then语句压入promise的微任务队列
  5. 执行console.log(“E”)
  6. 执行微任务队列,输出D;执行settimeout宏任务队列,输出A,B

结果:CEDAB

2.
setTimeout(function(){
    console.log('定时器开始啦')
});

new Promise(function(resolve){
    console.log('马上执行for循环啦');
    for(var i = 0; i < 10000; i++){
        i == 99 && resolve();
    }
}).then(function(){
    console.log('执行then函数啦')
});


console.log('代码执行结束');
// 马上执行for循环啦
// 代码执行结束
// 执行then函数啦
// 定时器开始啦
3.
console.log('1');

setTimeout(function() {
    console.log('2');
    new Promise(function(resolve) {
        console.log('3');
        resolve();
    }).then(function() {
        console.log('4')
    })
})
new Promise(function(resolve) {
    console.log('5');
    resolve();
}).then(function() {
    console.log('6')
})

setTimeout(function() {
    console.log('7');
    new Promise(function(resolve) {
        console.log('8');
        resolve();
    }).then(function() {
        console.log('9')
    })
})
//  1 5 6 2 3 4 7 8 9
  1. 执行宏任务完整script,输出1

  2. 异步setTimeout,压入宏任务queue,命名为settimeout1

  3. 执行promise,输出5,将.then压入微任务queue,命名为then1

  4. 异步setTimeout,压入宏任务queue,命名为settimeout2

    此时执行完第一个宏任务,则eventTable如下:

    宏任务 macrotask queue微任务 microtask queue
    settimeout1then1
    settimeout2
  5. 执行微任务,then1输出6

  6. 执行宏任务settimeout1,输出2 3 将then压入微任务,命名为then2

    此时执行完第二个宏任务,则eventTable如下:

    宏任务 macrotask queue微任务 microtask queue
    settimeout2then2
    settimeout2
  7. 执行微任务,then2输出4,

  8. 执行宏任务settimeout2,输出7 8 将then压入微任务,命名为then3

    此时执行完第三个宏任务,则eventTable如下:

    宏任务 macrotask queue微任务 macrotask queue
    then3
  9. 执行then3,输出9

垃圾回收机制

JavaScript的垃圾回收机制

Javascript 会找出不再使用的变量,不再使用意味着这个变量生命周期的结束。Javascript 中存在两种变量——全局变量和局部变量,全部变量的声明周期会一直持续,直到页面卸载

两种回收的实现思路

标记清除

当变量进入执行环境时标记为“进入环境”,当变量离开执行环境时则标记为“离开环境”,被标记为“进入环境”的变量是不能被回收的,因为它们正在被使用,而标记为“离开环境”的变量则可以被回收

function a(){
	name = 123 // 进入执行环境
}
a(); // 离开执行环境 name被回收

这种计数方式可能会因为闭包造成内存泄露(下文会讲到)

引用计数(不太常用)

统计引用类型变量声明后被引用的次数,当次数为 0 时,该变量将被回收

function b(){
    let a = {}; 此时次数为0 
    let b = a; 次数+1
    let c = a; 次数+1
    let b = 0; 次数-1
    let c = 0; 次数-1  计数为0 被回收
}

但可能出现互相引用的情况

function func5 () {
      let f = {}
      let g = {}
      f.prop = g
      g.prop = f
      // 由于 f 和 g 互相引用,计数永远不可能为 0
}

可能造成内存泄露的情况

意外的全局变量: 无法被回收
function a(){
	this.name = "mm"
}
console.log(name)

a的this指向window,此时name在全局中被保存,不会在a中被回收,导致内存泄露

定时器: 未被正确关闭,导致所引用的外部变量无法被释放
var m = test(){ console.log('lala') }
setInterval(function(){
	console.log(m);
},1000)

此时m无法被释放,且次操作没有意义

闭包: 会导致父级中的变量无法被释放
function m(){
    let d = '123'
    return function(){
        this.d = '456'
    }
}
let c = m();

此时d为活动对象,不会被销毁

dom 引用: dom 元素被删除时,内存中的引用未被正确清空
var m = {
	ele:document.getElementById('test')
}
function removeEle(){
	document.body.removeChild(document.getElementById('test'));
}
removeEle();
console.log(m);

此时仍然指向对于div的内存引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值