关于js内存泄露

内存泄露在前几年一直是个比较重要的话题,而如今虽然手机电脑内存容量较大,但依旧可能会存在严重的内存泄露问题。比如,一个 RN 界面存在内存泄露,一次访问回退,可能会导致占用内存增加 10M,以此不断切换页面,很快手机会出现卡顿的现象。

为什么 js 会发生内存泄露

这得先提到垃圾回收。线代浏览器都是自动回收垃圾,原理分两种:

  1. 引用计数垃圾回收

这一点和 objective-c 很像。当一个对象能访问另一个对象时,则意味着被访问的对象引用计数+1,当移除这种访问时,引用计数-1。当引用计数为 0 时,代表这此时作用域已经没有需要访问该对象的了,所以下一次垃圾回收会将该对象回收。

  1. 标记清除

该对象进入某个环境时,标记改变量为“进入环境”。从逻辑上讲,永远不能释放即进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到他们。而当变量离开环境时,则将其标记为:离开环境。

除非以下情况:

全局变量,而且当前执行环境还没有被退出

一般来讲全局变量是开发者明确需要全局引用的,所以一般无需主动回收。除非,在某些特定情况,已经明确某些对象不再使用了,而且也占用较大内存的话,可以在组件卸载的时候将变量置为 null,这是浏览器会在下一次垃圾回收时将该变量回收。示例如下:

componentWillunmount() {
	this.bigObject = null
}

闭包,闭包所储存的变量会延长它的生命周期

闭包往往是最容易出现内存泄露的地方

比如 setInterval 此类的定时器

经常出现的现象是组件已经卸载了,但是定时器还在跑,解决方案同样也是将定时器取消计时,示例如下:

componentDidMount() {
	this.time = setInterval(() => {
		this.now = new Date()
	})
}
componentWillunmount() {
	clearInterval(this.time)
}

addEventListener 添加的事件

添加的时间往往容易出现遗漏,当我们已经不需要该事件的时候,我们需要手动移除该监听,使用 removeEventListener

引用计数中循环引用

function problem() {
	var objA = new Object()
	var objB = new Object()
	objA.someOtherObject = objB
	objB.anotherObject = objA
}

办法是在页面卸载时手动将循环引用赋值为 null,比如:

objA.someOtherObject = null
objB.anotherObject = null

内存泄露调试技巧

react-native

safari 有一个调试工具,模拟器或者真机打开后,选择你的模拟器

20200728082950

点击工具栏的快照功能,此时等几秒就列表会出一个记录

此时再次操作手机或者模拟器,可以操作你认为可能出现内存泄露的路径,此时再点击工具栏的快照功能,出现新的一条记录后,即可对比两条记录的内存大小比较。

更多精彩文章可以看我的博客,如有错误,欢迎指正,共同进步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值