Leecason

vuePress-theme-reco Leecason    2018 - 2020
Leecason Leecason

Choose mode

  • dark
  • auto
  • light
主页
分类
  • CSS
  • FrontEnd
  • GraphQL
  • JavaScript
  • TypeScript
  • Vue
  • Webpack
  • 其它
  • 数据结构与算法
  • 浏览器相关
标签
时间线
GitHub
author-avatar

Leecason

80

Article

61

Tag

主页
分类
  • CSS
  • FrontEnd
  • GraphQL
  • JavaScript
  • TypeScript
  • Vue
  • Webpack
  • 其它
  • 数据结构与算法
  • 浏览器相关
标签
时间线
GitHub

垃圾回收与内存泄漏

vuePress-theme-reco Leecason    2018 - 2020

垃圾回收与内存泄漏

Leecason 2019-05-20 垃圾回收内存泄漏

# 前言

所谓内存泄漏就是不再使用的内存没有及时释放。

JavaScript 具有自动垃圾回收机制(Garbage Collection)。

JavaScript 程序每次创建字符串,数组,对象时,解释器都必须分配内存来存储那个实体,只要像这样动态分配了内存,最终都要释放这些内存以便它们能够被再用,否则,JS 的解释器将会消耗完系统中的所有可用的内存,造成系统崩溃。

# 垃圾回收机制

# 标记清除

JS 中最常用的垃圾回收方式

垃圾收集器在运行时会给存储在内存中的所有变量加上标记,然后,去掉环境中的变量以及被引用的变量的标记,之后再被加上的标记的变量为准备删除的变量,最后,垃圾收集器完成内存清除工作,销毁那些带标记的变量,回收它们占用的空间。

# 引用计数

语言引擎有一张“引用表”,保存了内存中所有的资源的引用次数。如果一个值的引用次数是 0,则表示不再使用了,可以释放这块内存。

# 引起内存泄漏

# 全局变量

可以启用严格模式解析 JavaScript ,避免意外的全局变量。

# 被遗忘的计时器或回调函数

var someResource = getData();
setInterval(function () {
    var node = document.getElementById('Node');
    if (node) {
      // 处理 node 和 someResource
      node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);
1
2
3
4
5
6
7
8

定时器包含对 someResource 的引用,定时器外部的变量不会释放。

# 闭包

闭包可以维持函数内局部变量,使其得不到释放。

# 没有清理的 DOM 元素引用

var elements = {
  button: document.getElementById('button'),
  image: document.getElementById('image'),
  text: document.getElementById('text')
};
function doStuff() {
  image.src = 'http://some.url/image';
  button.click();
  console.log(text.innerHTML);
}
function removeButton() {
  document.body.removeChild(document.getElementById('button'));
  // 此时,仍旧存在一个全局 elements 引用了 #button
  // button 元素仍旧在内存中,不能被 GC 回收。
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 参考

  • JavaScript中的垃圾回收和内存泄漏