这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战**node
最近在写小程序的过程当中,用到了不少的console.log
,开始是为了联调方便,一直没有删除,致使页面时不时有卡顿现象出现,开始以为页面从新刷新就行了,可是产品和测试不会答应的呀,后来排查了一下问题,才发现页面中出现不少种内存泄漏,想起以前面试时候这个问题也是考了不少次,一直没有总结,今天就趁机总结一下也好提醒本身平时多多注意。面试
首先咱们得清楚什么是内存泄漏,在引擎中有垃圾回收机制,主要针对一些程序中再也不使用的对象,清理回收释放掉内存,可是实际上垃圾回收机制并不会把再也不使用的对象所有回收掉。所以咱们在代码中要主动避免一些不利于引擎作垃圾回收的操做,这些没有被及时回收的对象内存,咱们叫它内存泄漏(Memory Leak)。小程序
来看看一些常见的内存泄漏案例:浏览器
大部分认为闭包就是函数内部嵌套并return一个函数,我翻了翻几本书中的描述:markdown
闭包涉及的范围是比较广了,如今看一个广泛的例子再认识一下闭包:闭包
function fnOne(){
let test = new Array(1000).fill('www')
return function(){
console.log('hahaha')
}
}
let fn1Child = fnOne()
fn1Child()
复制代码
这里由于return的函数中存在函数fnOne中的test变量引用,test不会被回收,也就形成了内存泄漏。app
怎么解决呢?就是在函数调用后,把外部的引用关系置空就行了:函数
function fnOne(){
let test = new Array(1000).fill('www')
return function(){
console.log(test)
return test
}
}
let fn1Child = fnOne();
fn1Child()
fn1Child = null;
复制代码
减小使用闭包,不正当的使用闭包可能会形成内存泄漏。post
在JavaScript中,垃圾回收是自动执行的,可是对于全局变量,垃圾回收器很难判断这些变量何时才不被须要,因此全局变量不会被回收,这时候就产生了内存泄漏:测试
function fn(){
// 没有声明从而制造了隐式全局变量test1
test1 = new Array(1000).fill('isboyjc1')
// 函数内部this指向window,制造了隐式全局变量test2
this.test2 = new Array(1000).fill('isboyjc2')
}
fn()
复制代码
let someResource = getData()
setInterval(() => {
const node = document.getElementById('Node')
if(node) {
node.innerHTML = JSON.stringify(someResource))
}
}, 1000)
复制代码
代码中,每隔一秒就把获得的数据放入到node节点中,可是在setInterval
没有结束以前,回调函数里的变量以及回调函数自己都没法被回收。这时候须要用到clearInterval
来清理这个定时器,才能回收someResource
。
setTiemout
也是一样的道理,不须要时候,及时去清除。
在代码中咱们会用到事件监听器,在组件内挂载相关的函数,组件销毁时候不主动清除时,其中的变量和函数会被认为是须要的,就不会被回收,这些内部引用的变量存储了大量数据,就会引发页面占用内存太高,形成内存泄漏。
不论是Vue仍是React,监听者模式实现一些消息通讯是 很广泛的,好比EventBus,当咱们实现了监听者模式在组件内挂载相关的函数,组件销毁时候不主动清除,就一样不会进行回收。这时候咱们要在beforeDestroy
组件销毁生命周期里及时去清除。
最后就是咱们在联调时候常见的console.log
了,咱们在浏览器控制台能够看到数据输出,输出对象的时候就也形成了内存泄漏。
差很少说完了常见的内存泄漏,下一篇就讲一下怎么排查定位代码中是否存在内存泄漏
。