写着写着前端浏览器的内存泄漏,我竟然被百度琳琅满目的博文给带跑偏了,竟然又追看了各种语言的垃圾回收机制。发现自己的知识储备真是贫瘠呀,怪不得面试老是没自信呢。
搜罗了博文之后发现,垃圾回收机制在之前系统级编程语言里(c||c++)是不存在的,程序员必须自己来控制内存管理,内存的申请与释放,稍有不慎内存的泄漏和溢出是家常便饭,后果不堪设想。
所以当后来开发出的新语言(php,python,java),都集成了自动的内存管理,也就是程序员在内存申请之后不用去考虑内存的释放。
那么javascript这个优秀且全能的语言当然也有自己的垃圾回收机制了,不过不同的javascript引擎有不同的垃圾回收机制,目前javascript的主流运行平台就是各大浏览器和node了,我们主要先说说浏览器。
各大浏览器采用的垃圾回收机制主要分为两种:
1,标记清除
这种机制是最常见的,它的大体思路是,当变量进入了执行环境(比如在函数中创建了它),它就被标记为了“进入环境”,成为了这个环境的活动对象,此时会给这个变量分配部分内存,但等到这个变量离开了执行环境(此时函数已经执行完毕),它就变成了死对象,等到浏览器发现了之后就会连同整个执行环境被销毁。
举个栗子喵:
function env() {
var name = 'Yubble'
console.log(name + '最好了,哼')
}
env() // 这里打个debug // 运行到这一行的时候,env函数开启了自己的小周天,我们现在就跳进env里面去看,飞~
好啦各位看官,我们现在已经进入了给env分配的堆空间中(大家克服一下,想象一下)
var name = 'Yubble' // 此时这个标量进入了执行环境,被激活车活动对象了
cconsole.log(name + '最好了,哼') // 然后又说了一句Yubble最帅,哼😆
就这样,env的执行结束了,浏览器里的内存管理员问他:“你还有用吗?”,env茫然的摇了摇头,于是生命到了尽头~
等到了 env() 的下一行,他就被浏览器里带着墨镜的黑衣人整体带走了....
看了上面的一系列虐心剧是不是忽然有点明白了,为什么闭包可能会在某些早期浏览器中引起内存泄漏,是的,关键就在于内存管理员说的那句“你还有用吗?”,闭包的一大功能就是将函数中的变量保存下来供后续代码使用...
2,引用计数
这种垃圾回收策略我们也提一下子吧,谁让红宝书都将它讲解了呢。它的工作原理在于跟踪记录每个值被引用的次数(被引用肯定是指引用类型咯,基础的5种类型也不会造成内存泄漏的)。
当我们把一个引用类型的地址赋值给变量时,这个地址的引用次数就是1,此时同一个地址又被赋值给另一个变量,它的引用次数加1。
当我们把被赋值的变量给赋予了另外一个值,此时引用次数减一。(我靠多绕啊,这样浏览器内存清的掉才怪呢,性能也高不到哪儿去吧--来自一个菜鸡的心声)
语言总是很苍白的,我们用代码来举例
function count() {
var a = {} // 此时新建了几个对象,它的引用计数为0
var b = a // 呐,这个时候a对象就被引用了一次,引用次数1
var c = a // a对象又被引用啦,它已经被引用两次啦,引用次数2
b = null // 此时b被清空了,所以a的引用对象少了一个,引用次数1
}
但是如果我们对象相互引用怎么弄嘞,比如这样:
function count() {
var a = {}
var b = {}
a.child = b
b.child = a
}
如果要是在引用计数的策略下这两个对象就似乎形成了闭环,永远都不会释放对方。
所以在早期某些浏览器中,我们如果频繁调用count可能就会引起内存泄漏。
这次学习引荐了“js红宝书”以及“js晋级篇-前端内存泄漏”,如果各位看官想要一起讨论diss一下内存泄漏的触发原因,请浏览在下另一篇博文,前端内存泄漏之形成篇😄。再次跪谢各位看官指教~
网友评论