大多数情况下,垃圾回收器会帮我们及时释放内存,一般不会发生内存泄漏。但是有些场景是内存泄漏的高发区,我们在使用的时候一定要注意:
-
我们在开发的时候经常会使用
console
在控制台打印信息,但这也会带来一个问题:被console
使用的对象是不能被垃圾回收的,这就可能会导致内存泄漏。因此在生产环境中不建议使用console.log()
的理由就又可以加上一条避免内存泄漏了。 -
被全局变量、全局函数引用的对象,在Vue组件销毁时未清除,可能会导致内存泄漏
1// Vue3 2<script setup> 3import {onMounted, onBeforeUnmount, reactive} from 'vue' 4const arr = reactive([1,2,3]); 5onMounted(() => { 6 window.arr = arr; // 被全局变量引用 7 window.arrFunc = () => { 8 console.log(arr); // 被全局函数引用 9 } 10}) 11// 正确的方式 12onBeforeUnmount(() => { 13 window.arr = null; 14 window.arrFunc = null; 15}) 16</script>
-
定时器未及时在Vue组件销毁时清除,可能会导致内存泄漏
1// Vue3 2<script setup> 3import {onMounted, onBeforeUnmount, reactive} from 'vue' 4const arr = reactive([1,2,3]); 5const timer = reactive(null); 6onMounted(() => { 7 setInterval(() => { 8 console.log(arr); // arr被定时器占用,无法被垃圾回收 9 }, 200); 10 // 正确的方式 11 timer = setInterval(() => { 12 console.log(arr); 13 }, 200); 14}) 15// 正确的方式 16onBeforeUnmount(() => { 17 if (timer) { 18 clearInterval(timer); 19 timer = null; 20 } 21}) 22</script>
setTimeout
和setInterval
两个定时器在使用时都应该注意是否需要清理定时器,特别是setInterval
,一定要注意清除。 -
绑定的事件未及时在Vue组件销毁时清除,可能会导致内存泄漏
绑定事件在实际开发中经常遇到,我们一般使用
addEventListener
来创建。1// Vue3 2<script setup> 3import {onMounted, onBeforeUnmount, reactive} from 'vue' 4const arr = reactive([1,2,3]); 5const printArr = () => { 6 console.log(arr) 7} 8onMounted(() => { 9 // 监听事件绑定的函数为匿名函数,将无法被清除 10 window.addEventListener('click', () => { 11 console.log(arr); // 全局绑定的click事件,arr被引用,将无法被垃圾回收 12 }) 13 // 正确的方式 14 window.addEventListener('click', printArr); 15}) 16// 正确的方式 17onBeforeUnmount(() => { 18 // 注意清除绑定事件需要前后是同一个函数,如果函数不同将不会清除 19 window.removeEventListener('click', printArr); 20}) 21</script>
-
被自定义事件引用,在Vue组件销毁时未清除,可能会导致内存泄漏
自定义事件通过
emit/on
来发起和监听,清除自定义事件和绑定事件差不多,不同的是需要调用off
方法1// Vue3 2<script setup> 3import {onMounted, onBeforeUnmount, reactive} from 'vue' 4import event from './event.js'; // 自定义事件 5const arr = reactive([1,2,3]); 6const printArr = () => { 7 console.log(arr) 8} 9onMounted(() => { 10 // 使用匿名函数,会导致自定义事件无法被清除 11 event.on('printArr', () => { 12 console.log(arr) 13 }) 14 // 正确的方式 15 event.on('printArr', printArr) 16}) 17// 正确的方式 18onBeforeUnmount(() => { 19 // 注意清除自定义事件需要前后是同一个函数,如果函数不同将不会清除 20 event.off('printArr', printArr) 21}) 22</script>
除了及时清除监听器、事件等,对于全局变量的引用,我们可以选择WeakMap
、WeakSet
等弱引用数据类型。这样的话,即使我们引用的对象数据要被垃圾回收,弱引用的全局变量并不会阻止GC。
个人笔记记录 2021 ~ 2025