javascript 垃圾回收机制

垃圾回收有两种实现方式,分别是标记清除引用计数

标记清除

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

引用计数

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

但是引用计数的方式,有一个相对明显的缺点——循环引用

像上面这种情况就需要手动将变量的内存释放

在现代浏览器中,Javascript 使用的方式是标记清除,所以我们无需担心循环引用的问题

什么是内存泄露?

本质上讲, 内存泄露就是不再被需要的内存, 由于某种原因, 无法被释放.

常见的内存泄露案例

1)全局变量照成内存泄露

在 JS 中处理未被声明的变量, 上述范例中的会把 name , 定义到全局对象中, 在浏览器中就是 window 上. 在页面中的全局变量, 只有当页面被关闭后才会被销毁. 所以这种写法就会造成内存泄露, 当然在这个例子中泄露的只是一个简单的字符串, 但是在实际的代码中, 往往情况会更加糟糕.

另外一种意外创建全局变量的情况.

在这种情况下this被指向了全局变量 window, 意外的创建了全局变量. 我们谈到了一些意外情况下定义的全局变量, 代码中也有一些我们明确定义的全局变量. 如果使用这些全局变量用来暂存大量的数据, 记得在使用后, 对其重新赋值为 null.

2)未销毁的定时器和回调函数照成内存泄露

如果后续 oHtml 元素被移除, 整个定时器实际上没有任何作用. 但如果你没有回收定时器, 整个定时器依然有效, 不但定时器无法被内存回收, 定时器函数中的依赖也无法回收. 在这个案例中的 fn也无法被回收.

3 ) 闭包照成内存泄露

在 JS 开发中, 我们会经常用到闭包, 一个内部函数, 有权访问包含其的外部函数中的变量. 下面这种情况下, 闭包也会造成内存泄露.

3)DOM 引用照成内存泄露

很多时候, 我们对 Dom 的操作, 会把 Dom 的引用保存在一个数组或者 Map 中.

上述案例中, 即使我们对于 test 元素进行了移除, 但是仍然有对 test 元素的引用, 依然无法对齐进行内存回收. 另外需要注意的一个点是, 对于一个 Dom 树的叶子节点的引用. 举个例子: 如果我们引用了一个表格中的 td 元素, 一旦在 Dom 中删除了整个表格, 我们直观的觉得内存回收应该回收除了被引用的 td 外的其他元素. 但是事实上, 这个 td 元素是整个表格的一个子元素, 并保留对于其父元素的引用. 这就会导致对于整个表格, 都无法进行内存回收. 所以我们要小心处理对于 Dom 元素的引用.

微信公众号:我的web前端自救之路

回复 加群 ,跟大佬们一起交流技术吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值