面试-js 内存管理

发布于:2023-03-18 ⋅ 阅读:(770) ⋅ 点赞:(0)

1. 内存管理

  • 分配内存:挖坑,要根据不同的类型分配不同的内容

    • js 基础类型:string、number、boolean、undefined、null、symbol。占用空间大小固定、体积轻量。放在栈内存中存储。
    • js 复杂类型:Object。占用空间大小不固定。放在堆内存中存储。
  • 读写内存:用坑

    • js 基础类型:获取时直接从栈中取走变量的值。
    • js 复杂类型:获取时,先从栈内存中获取对象的引用(堆内存中的地址),然后再去堆内存中查询,拿到具体的数据。
  • 释放内存:还坑,垃圾回收

    • 引用计数法:

      • 现代浏览器已经不用这种了
      • 内存中每一个变量都对应一个引用计数,当计数为0的时候释放内存
      • 存在的问题:无法删除循环引用的对象,容易引起内存泄漏
    • 标记清除法:

      • 从 window 对象开始,扫描所有可以通过根对象触达的变量,这些对象被标记为‘可触达’。
      • 遍历所有对象清除没标记的对象,并将标记恢复到默认。
      • 回收相应的空间
      • 缺点:回收的对象在地址上是不连续的,导致空间虽然被回收了,但是不连续,导致后续分配空间的不好使用,而浪费空间。而且不会立即回收垃圾对象
    • 标记整理法:

      • 标记阶段是一样的;
      • 清除之前会先整理空间,移动位置,使被释放的空间在一个连续的空间。
      • 新生代(存活时间短,占比小)+ 老生代。新生代(from + to),存活的从 from 移到 to,不存活的释放;然后互换位置;如果to中超过 25%,则放到老生代。老生代:将活的移动到一侧;清除边界外的所有;
    • 在实际中还做了一些优化:

      • 遍历一次对象的耗时可能比较久,在执行时存在一定的延迟。所以引擎会将垃圾回收分解为几个部分,各个部分分别执行,减小延迟。
      • 为了减少对执行的影响,垃圾回收只在 CPU 空闲的时候运行

    2. 内存泄漏

  • 意外的全局变量
  • 没有清除 setInterval、连续的 setTimout
  • 没有删除对 DOM 的引用