html前端给手机号加敏处理安全,Web 前端开发日志(三):HTML 节点的内存泄露问题...

文章为在下以前开发时的一些记录与当时的思考, 学习之初的内容总会有所考虑不周, 如果出错还请多多指教.

TL;DR

对 DOM 节点的引用会使得节点一直在内存中存储而不会进行释放.

问题...

请各位考虑一下如下代码,这里有一个简易的 HTML:

My Div

  • Hero
  • Cows
  • Bugs

Delete My Div

复制代码

还有一段比较丑的逻辑:

function deleteMyDiv (){

myDiv.parentElement.removeChild(myDiv)

}

复制代码

请问,点击 "Delete My Div" 按钮时,节点 #my-div 消失了么?

用 Memory 抓一下 Heap 看一下

我们来用 Chrome 开发者工具中抓一下 Heap 观察一下,看看是不是能找到 Detached DOM.

Detached DOM 代表一个 HTML 节点在 HTML 中被移除,但在内存中还保持引用的状态,意思就是,没删干净侧漏啦!

我们来实际抓一下看看,我们抓两次快照,第一次是在点击删除按钮前的快照,如下图:

768264c59668f472133f5d2ec4a7bfd6.png

我们在搜索框中输入 detached,看起来并没有 Detached 节点.

我们点击页面中的 "Delete My Div" 后来抓第二次:

ca0b34aaf162e0e6b9e0efab70b78606.png

嚯,这就有了!选中它看看:

90255bcb46cff7c47caafce1e20eac26.png

看看这个 div#my-div,I'm angry!

稍微调整一下逻辑

我们来稍微调整一下逻辑:

function getMyDiv (){

return document.querySelector('#my-div')

}

function deleteMyDiv (){

const myDiv = getMyDiv()

myDiv.parentElement.removeChild(myDiv)

}

复制代码

然后刷新页面,再抓一个新的快照:

212fc655d1a9817b6983c4a9f5bc05d1.png

这次没了!

问题在哪里?

最早的代码问题出现在了,deleteMyDiv 对 myDiv 进行了引用,而且 deleteMyDiv 没有进行回收,所以导致 myDiv 的一直存在.

我们再仔细看以下刚才截取的快照:

e910898ec0806a01ce13a5445d9d593e.png

就算是将 myDiv 从 HTML 中删除,内存中也会一直保存其数据不会释放.

修改之后的代码没有任何地方保持了对 myDiv 的引用,所以在删除操作执行完毕后会立刻释放 div#my-div 节点.

实际上这样的情况在业务逻辑中非常容易出现,比如创建一个比较复杂的节点,这个节点中包含了很多细碎的节点,甚至这些节点是从别的业务服务中传入进来的,这时就很难保证这些细碎的节点没有被其创建函数或外部代码引用,所以就算在 HTML 中删除,也很有可能造成泄漏.

子节点呢?

如果删除一个节点,这个节点没有被直接引用,但里面的子节点被引用,会怎么样?

Inner DIV

Delete My Div

复制代码// 加入 innerDiv.

const innerDiv = document.querySelector('#inner-div')

function getInnerDiv (){

return innerDiv

}

// 下边还是之前的代码.

function getMyDiv (){

return document.querySelector('#my-div')

}

function deleteMyDiv (){

const myDiv = getMyDiv()

myDiv.parentElement.removeChild(myDiv)

}

复制代码

截取快照:

7b50b5435d7719593cc2818672ccf00c.png

4cf87bedeb3f9a235937b2f54946e3fa.png

可以看到两个都已经变成 Detached Dom,批判一番!🐸🔫

总结

实际上在下对于这种情况在下目前并没有非常好的预防实践,只能说大家对敏感的 DOM 操作逻辑进行谨慎地编写,并在出现问题的时候借助工具快速排查,如果有更好的实践还请大家多分享交流.

对于性能要求比较高的场景,使用原生代码创建节点还是请小心谨慎,避免 Detached Dom 带来的内存泄漏问题.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值