事情的经过
前段时间群里的老哥提出了一个疑问
image.png测试
根据上述的情况,我跟群里老哥做了一个demo来测试问题出在哪
<!DOCTYPE html>
<html>
<body>
<div id="app">
<button id="create-input">Create input</button>
<button id="destroy-input">Destroy input</button>
<br>
<button id="create-div">Create div</button>
<button id="destroy-div">Destroy div</button>
</div>
<script>
const getId = (str) => document.getElementById(str)
function createTest(elem) {
const CreateBtn = getId(`create-${elem}`)
const DestroyBtn = getId(`destroy-${elem}`)
const onAddClick = () => {
let input = document.createElement(elem)
input.id = elem
// 给dom绑定大量对象
input._a_ = new Array(1000000).fill('1')
document.body.appendChild(input)
input = null
}
const onRemoveClick = () => {
let input = getId(elem)
if (input) {
input.parentNode.removeChild(input)
}
input = null
}
CreateBtn.addEventListener('click', onAddClick)
DestroyBtn.addEventListener('click', onRemoveClick)
}
createTest('div')
createTest('input')
</script>
</body>
</html>
创建input/div并手动销毁的演示,操作完input后需要刷新页面重置当前window的内存
performance.gif performance2.gif测试结果
根据上述简单测试,比对memory和perfomance两个工具,能够得到一些结论:
- 大对象没有在销毁DOM元素后直接GC,而是当下一次有新的大对象创建时(这里是大对象绑定在DOM上),才会处理原有大对象的内存占用
- Div的GC比较彻底,Input元素几乎没有GC掉原来的垃圾
河大点评了一下:
image.png那位老哥最后发邮件咨询了一下chromium团队:
image.png总结
- 别随便往DOM对象上绑定东西,注意销毁事件绑定
- Input元素对象,由于undo/redo的需求,存在特殊情况
- 该重新学一下V8垃圾回收机制了(
网友评论