放肆青春的博客
首页
前端
算法
网络
面试
技术
后端
运维
杂项
数据库
工具
网址
电脑
个人
文章
  • 分类
  • 标签
  • 归档
github (opens new window)
gitee (opens new window)

放肆青春

一个前端菜鸟的技术成长之路
首页
前端
算法
网络
面试
技术
后端
运维
杂项
数据库
工具
网址
电脑
个人
文章
  • 分类
  • 标签
  • 归档
github (opens new window)
gitee (opens new window)
  • 前端

    • 前端 概览
    • 前端汇总

    • front 博文

    • front 项目总结

    • front 高级

    • front tools

  • vue

    • vue 概览
    • vue 汇总

    • vue 博文

    • vue 项目总结

    • vue 高级

  • html

    • html 概览
    • html 汇总

    • html 博文

  • css

    • css 概览
    • css 汇总

    • css 博文

    • sass

    • less

  • js

    • javascript 概览
    • JS 汇总

    • ES6

    • JS 博文

      • js 基础语法
      • js 数据类型
      • js 字符串
      • js 数组
      • js 对象
      • js 变量
      • js 函数
      • js 事件
      • js 循环
      • js 浅拷贝和深拷贝
      • js 动画
      • js DOM
      • js 防抖节流
      • js 原型及原型链
      • js this
      • js 作用域
      • js 继承
      • js 闭包
      • js 内存
        • 内存
          • 内存生命周期
          • 内存管理系统:手动 or 自动
          • 内存引用
          • 火焰图
        • 内存泄漏
          • 1. 意外的全局变量
          • 2.dom 清空时,还存在引用
          • 3. 被遗忘的定时器和回调函数
          • 4. 不规范地使用闭包
          • vue 中的内存泄漏
          • 怎么避免内存泄漏
          • 内存泄漏的排查方法
        • 内存溢出
          • 内存溢出的原因
          • 内存溢出的解决方案
        • 栈内存和堆内存
          • 栈内存
          • 堆内存
          • 栈内存和堆内存对比
          • 闭包与堆内存
          • 栈内存和堆内存的垃圾回收
      • js垃圾回收
    • JS 工具

  • node

    • node 概览
    • node 汇总

    • node 框架

    • node 博文

  • react

    • react 概览
    • react 汇总

    • react 博文

    • react 高级

  • 微信小程序

    • 微信小程序 概览
    • 微信小程序总结
    • 微信小程序文章
    • 微信小程序 博文

    • 微信小程序 高级

  • 微信公众号

    • 微信公众号 概览
    • 微信公众号总结
    • 微信公众号文章
  • 多端开发

    • 多端开发
    • dsbridge 概览
    • jsbridge 概览
    • webview
    • uniapp

      • uniapp 概览
    • taro

      • taro 概览
    • flutter

      • flutter 概览
      • flutter 环境搭建
    • electron

      • electron 概览
  • front
放肆青春
2021-03-22

js 内存

# 内存

# 内存生命周期

不管什么程序语言,内存生命周期基本是一致的:

  1. 分配内存

  2. 使用内存(读或写)

  3. 释放内存

# 内存管理系统:手动 or 自动

  1. 低级语言:像 C 语言这样的低级语言一般都有底层的内存管理接口,比如 malloc()和 free()。

  2. 高级语言:JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。 释放的过程称为垃圾回收。这个“自动”是混乱的根源,并让 JavaScript(和其他高级语言)开发者错误的感觉他们可以不关心内存管理。

内存:由可读写单元组成,表示一片可操作空间;

管理:人为的去操作一片空间的申请、使用和释放;

内存管理:开发者主动申请空间、使用空间、释放空间;

管理流程:申请-使用-释放

# 内存引用

如果一个对象可以访问另一个对象(可以是隐式的或显式的),则称该对象引用另一个对象。例如, 一个 JavaScript 引用了它的 prototype (隐式引用)和它的属性值(显式引用)。

# 火焰图

火焰图的生成过程有两步:

  1. 使用 Profiler 工具生成 trace 文件;

  2. 将 trace 文件转换为 svg 格式的火焰图文件;

FlameGraph(制图工具):包含堆栈跟踪的任何概要文件数据生成火焰图,包括从以下概要分析工具

Linux: perf, eBPF, SystemTap, and ktap

Solaris, illumos, FreeBSD: DTrace

Mac OS X: DTrace and Instruments

Windows: Xperf.exe

参考:https://zhuanlan.zhihu.com/p/147875569 (opens new window)

http://liuxiang.github.io/2018/02/05/火焰图(flame graph)是性能分析/ (opens new window)

# 内存泄漏

内存泄漏 memory leak:是指程序在申请内存后,无法释放已申请的内存空间

一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

memory leak 会最终会导致 out of memory!

合理的使用 WeakMap 和 WeakSet,能帮助我们避免内存泄漏

常见的内存泄漏:

  1. 意外的全局变量

  2. dom 清空时,还存在引用

  3. 定时器中的内存泄漏

  4. 不规范地使用闭包

# 1. 意外的全局变量

变量并没有声明.JS 就会默认将它变为全局变量,这样在页面关闭之前都不会被释放.

function foo() {
  bar = 2;
  console.log("bar没有被声明!");
}
1
2
3
4

避免:使用严格模式

# 2.dom 清空时,还存在引用

很多时候,为了方便存取,经常会将 DOM 结点暂时存储到数据结构中.但是在不需要该 DOM 节点时,忘记解除对它的引用,则会造成内存泄露.

var refA = document.getElementById("refA");
document.body.removeChild(refA); // dom删除了
console.log(refA, "refA"); // 但是还存在引用
// 去掉DOM节点的引用
refA = null;
1
2
3
4
5

与此类似情景还有: DOM 节点绑定了事件, 但是在移除的时候没有解除事件绑定,那么仅仅移除 DOM 节点也是没用的

避免:dom 引用置为 null

# 3. 被遗忘的定时器和回调函数

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

如果没有清除定时器,那么 someResource 就不会被释放,如果刚好它又占用了较大内存,就会引发性能问题. 但是 setTimeout ,它计时结束后它的回调里面引用的对象占用的内存是可以被回收的. 当然有些场景 setTimeout 的计时可能很长, 这样的情况下也是需要纳入考虑的.

避免: 在定时器完成工作的时候,手动清除定时器

# 4. 不规范地使用闭包

相互循环引用

function foo() {
  var a = {};
  function bar() {
    console.log(a);
  }
  a.fn = bar;
  return bar;
}
1
2
3
4
5
6
7
8

bar 作为一个闭包,即使它内部什么都没有,foo 中的所有变量都还是隐式地被 bar 所引用。 即使 bar 内什么都没有还是造成了循环引用,那真正的解决办法就是,不要将 a.fn = bar.

注意点:

闭包,闭包和内存泄漏没有半毛钱关系,只是由于 IE9 之前的版本垃圾收集机制的原因,导致内存无法进行回收,这是 IE 的问题,现代浏览器基本都不存在这个问题。当然闭包要是使用不当肯定是会造成内存泄漏。

# vue 中的内存泄漏

  1. DOM 中的 addEventLisner 函数及派生的事件监听没有解除绑定

解决办法:需要在 beforeDestroy 中做对应解绑处理;

  1. 组件中使用了 setInterval,需要在 beforeDestroy 中做对应销毁处理

  2. 绑在 EventBus 的事件没有解绑

解决办法:this.$EventBus.$off()

  1. Echarts 的实例没有释放

解决办法:echarts 的实例在 beforeDestroy()方法释放

beforeDestroy () {
  this.chart.clear()
}
1
2
3

# 怎么避免内存泄漏

  1. 减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收(即赋值为 null);

  2. 避免循环引用,避免“死循环”之类的 ;

  3. 避免创建过多的对象 原则:不用了的东西要记得及时归还。

  4. 减少层级过多的引用

# 内存泄漏的排查方法

  1. chrome Performance

启用 Memory(内存)复选框。开始录制前先点击垃圾回收-->点击开始录制-->点击垃圾回收-->点击结束录制

  1. 使用 Chrome 的开发者工具 Memory 来进行快照对比。

  2. 如果是在 Node 环境下,可以用 Node 提供的 process.memoryUsage()方法来检查内存泄露

参考:https://blog.csdn.net/c11073138/article/details/84700482 (opens new window)

# 内存溢出

内存溢出 out of memory:是一种程序运行出现的错误, 是指程序在申请内存时,没有足够的内存空间供其使用

# 内存溢出的原因

  1. 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;

  2. 集合类中有对对象的引用,使用完后未清空,使得 JVM 不能回收;

  3. 代码中存在死循环或循环产生过多重复的对象实体;

  4. 使用的第三方软件中的 BUG;

  5. 启动参数内存值设定的过小

# 内存溢出的解决方案

  1. 修改 JVM 启动参数,直接增加内存。(-Xms,-Xmx 参数一定不要忘记加。)

  2. 检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。

  3. 检查代码中是否有死循环或递归调用

  4. 检查是否有大循环重复产生新对象实体。

  5. 检查对数据库查询中,是否有一次获得全部数据的查询(如果一次取十万条记录到内存,就可能引起内存溢出)

# 栈内存和堆内存

参考:「前端进阶」JS 中的栈内存堆内存https://juejin.cn/post/6844903873992196110 (opens new window)

指针就是通过一个变量去指向一个有的变量或者说是对象,从而产生一种绑定

# 栈内存

# 堆内存

# 栈内存和堆内存对比

image

栈内存和堆内存的优缺点:

在 JS 中,基本数据类型变量大小固定,并且操作简单容易,所以把它们放入栈中存储。 引用类型变量大小不固定,所以把它们分配给堆中,让他们申请空间的时候自己确定大小,这样把它们分开存储能够使得程序运行起来占用的内存最小。

栈内存由于它的特点,所以它的系统效率较高。

堆内存需要分配空间和地址,还要把地址存到栈中,所以效率低于栈。

# 闭包与堆内存

闭包中的变量并不保存中栈内存中,而是保存在堆内存中。 这也就解释了函数调用之后之后为什么闭包还能引用到函数内的变量。

# 栈内存和堆内存的垃圾回收

栈内存中变量一般在它的当前执行环境结束就会被销毁被垃圾回收制回收, 而堆内存中的变量则不会,因为不确定其他的地方是不是还有一些对它的引用。 堆内存中的变量只有在所有对它的引用都结束的时候才会被回收。

更新时间: 1/14/2022, 6:21:39 PM
js 闭包
js垃圾回收

← js 闭包 js垃圾回收→

最近更新
01
前端权限管理
02-24
02
vue2指令
02-24
03
vue2 hook
02-24
更多文章>
Theme by Vdoing | Copyright © 2019-2022 放肆青春
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式