许多前面都会用 console.log 调节,先不说调节高效率如何,最先 console.log 有一个致命性的难题:也会导致内存泄漏。
为什么这样说呢?
用 Performance 和 Memory 专用工具分析一下就明白了。
我们准备这样一段编码:
一个按键,点一下以后创建一个二维数组,实行一些测算。
比较常见的逻辑性。
大家最终加了一个 console.log 打印出了一下这一二维数组。
起一个静态数据服务项目:
点一下 performance 中的垃圾分类回收按键,手动式开启一次 GC:
启用 Memory,然后就拍摄,点一下 3 次按键,再执行一次 GC:
你就会发现运行内存是这样子的:
cpu占用有三次提高,只要我们点一下三次按键的时候就会建立 3 次大二维数组。
不过最后大家手动式 GC 以后并没下降下来,其实就是这个小二维数组没被回收利用。
按道理说,执行命令完,那用的运行内存就需要被释放,随后再执行其他编码,结论这一段执行命令完以后大二维数组仍然占据了运行内存,那样其他编码再执行时可用内存也就少了。
这便是出现了内存泄漏,其实就是执行命令完后不增加内存的恶意程序。
有朋友说,仅仅那么一点运行内存没什么问题呀,总之可用内存还有很多。
但是如果你的代码要跑很长一段时间,这一段编码要实行好多次呢?
每一次实行都是会占有一部分运行内存不释放出来,慢慢地运行内存就不够用了,甚至会导致程序崩溃。
例如当这一段执行命令个 9 次,cpu占用就增加了 9 一个大二维数组的运行内存:
再好实行几回呢?
是否就会有奔溃的隐患了。
那为啥说成 console.log 造成的呢?
我们来看一下无需 console.log 是怎么样的:
注释掉 console.log,再次跑。
你就会发现现今内存分配状况是这样子的:
分派了三次运行内存,可是 GC 后又落下了。
这才是真正并没有内存泄漏好编码。
那为啥 console.log 也会导致内存泄漏呢?
由于控制面板打印目标,你是否有可能会进行看?那么如果这一目标在内存中没了,肯定就看不到了?
因此有这种引入在,电脑浏览器不容易将你打印对象内存优化掉。
许多学生说,那么我不打开控制面板,肯定就没有那个引用了?
答案是否定的:
我点一下了几次后,打开控制面板,依旧是能够看见这一对象,表明没被 GC。
换句话说用 console.log 打印出目标的代码一定是有内存泄漏的。
自然,也不仅仅是 console.log 也会导致内存泄漏,还有其他的 4 个原因:
- 计时器用掉并没有消除,那每一次实行都是会多一个计时器的cpu占用,这便是内存泄漏
- 原素从 dom 移除开,但是还是有一个自变量引入着他,这种分散的 dom 原素不会被回收利用。每运行一次编码,便会空出分散的 dom 元素运行内存,那也是内存泄漏
- 闭包引用了某一自变量,这一自变量不被回收利用,如果是这样的闭包较多,那每一次实行都是会空出那些被引用变量的cpu占用。那样引入大对象闭包得多以后,也会造成内存问题
- 局部变量,这一原本也不会被 GC,需要注意局部变量的应用
总而言之,局部变量、闭包提及的自变量、被删除的 dom 依然被引入、计时器用完了没消除、console.log 都会出现执行命令完后,但是还占有着一部分运行内存的恶意程序,其实就是内存泄漏。
留意,这儿是指应用完成后并没有回收利用,使用阶段的运行内存提高是正常。
那怎么排查呢?
performance 专用工具就能:
点一下内存分配状况某个点,便会定位到 performance 里的某一每日任务的代码,点一下能够在下文见到详细信息:
这个就精准定位到释放内存的代码,分析一下哪儿会出现难题就可以。
自然,前提条件还是得实行先 GC,继续做一些实际操作,再 GC 这个步骤。
这是从编码视角来剖析内存泄漏,实际上也可以从内存中目标的视角,这一是由 Memory 专用工具:
先 GC,拍摄一次运行内存快照更新,再点击几回按键,随后 GC,再拍摄一次运行内存快照更新。
步骤和用 performance 讲解的情况下一样。
取得2次运行内存快照更新是可以判断出有内存泄漏的:
能够看见 GC 后cpu占用仍然增加了。
快照更新记录了这个时刻内存中全部对象情况:
比照2次快照更新,就能找到转变的那一部分:
例如此刻能够看见较大的存储空间提高是 array 目标:
之后就可以从 array 的角度去思考是什么导致的内存泄漏了。
除此之外,memory 也有实时分析的一种手段:
挑选第二个,随后点几回按键:
其实没必要手动式 GC,JS 模块也会做 GC。
除掉 console.log 再拍摄是这样子的:
除开最初局部变量会配置一些运行内存之外,点击图标以后的运行内存变蓝之后又变灰了,其实就是被 GC 了。
那样你点几回按键,cpu占用也没有提高。
这便是执行命令完,会回收利用全部需要用到的运行内存好编码。
而前面的那个就是每一次执行命令,都是会占有一部分运行内存不释放出来的内存泄漏编码。
你也可以看到每一次内存分配的对象是啥:
无论要用 Performance 专用工具或是 Memory 专用工具,都能够发觉 console.log 有内存泄漏问题。因此还是最好不要用这一来调节了。
的话应该用什么?
用 debugger 呀,不论是 vscode debugger 或是 chrome devtools 的都能够:
你可以添加一个 logpoint 代替 console.log 打印出:
执行命令到这儿便会打印出:
而你的编码里不用写 console.log。
除此之外,好多地方能用中断点取代打印出:
能够看见执行命令路线和修饰符,难道不是更有效?
汇总
console.log 也会导致内存泄漏,其实就是执行命令完后,却还占据了一部分运行内存的恶意程序。
除开 console.log,分散的 dom 被自变量引入、局部变量、自变量被闭包引入、计时器没消除也会造成内存泄漏。
我们可以通过 Performance 工具 Memory 专用工具剖析内存泄漏。
先手动式 GC,随后实行一些实际操作,再 GC,假如运行内存并没有返回实行前,就证明这一段编码有内存泄漏,能够再换 Performance 定位到编码部位剖析编码。
Memory 专用工具是以运行内存对象角度而言,能够对2次快照更新做 diff,看看是什么目标泄露了。
还可以实时监测cpu占用状况,看看是不是存有内存泄漏,目标是什么。
console.log 调节高效率也不是很高,能够换为 logpoint,或是打断点。
千万别把 console.log 上生产制造!要不然这种有内存泄漏的代码,一旦实行时间长了会出现难题。
实际上一般新项目也还好,不容易长期性跑,可是相近大屏幕新项目这类长期性跑得,一旦有内存泄漏,一定会奔溃,仅有时间的长短的差别。
(本文有点儿不正确,在续篇更改了:console.log 一定也会导致内存泄漏?不打开 devtools 也就不会)