背景

  • 每个页面都会占用电脑的一部分内存来执行代码。小到一个变量大到整个程序的所有资源由内存来分配。
  • 一个标签页在32位系统的最大内存为0.7G左右,在64位系统是1.4g左右。

    • 所以,一个开发工程师对于内存的把控是很重要的,会直接影响到用户的体验。

      概念

  • 每个页面都有一个完整的内存布局。主要是分为3个板块:

    1. 栈(stack):主要负责保存了基本类型的数据以及引用类型数据在堆中的内存地址。
    2. 堆(heap):主要是用于保存引用类型的数据。
    3. 常量池(constant pool):是一个逻辑上的概念,主要是保存常量以及字符串等。
  • 理解:以上的内存布局只是逻辑上的东西,实际内存中就是一块区域(堆:heap)。
  • 内存中的每个区域都是有一个地址的。

    作用

    变量如何进行内存分配

  1. 基本类型的数据的内存分配

    1. 当定义一个变量为基本类型数据时,那么JavaScript会在栈里分配一个空间,将数据保存到该空间中,如果定义了新的变量等于旧变量,那么JavaScript会将旧变量对应内存空间中的数据进行拷贝,并分配一个新空间并将拷贝的数据放在新空间里。
      1. let a = 1;
      2. let b = a;
      3. a = 2;
      4. console.log(b);// 1
  2. 引用类型数据的内存分配

    1. 当定义一个变量为引用类型数据时,先在堆当中分配一块空间,并将数据放入空间中。之后在栈中分配一块空间,保存堆中数据对应空间的内存地址。当定义一个新的变量等于旧变量时,新变量只是在栈中将旧变量保存的数据(堆中的内存地址)进行拷贝并赋给新的变量。
      1. let obj = {};
      2. obj.name = "张三";
      3. let obj2 = obj;
      4. obj.age = 12;
      5. console.log(obj2);//{name:'张三',age:12}

      垃圾回收(回收内存)

  • 概念:JavaScript内部有全自动的内存回收程序,无需开发人员做任何事情。但是一个良好的开发规范可以让内存得到充分有效的利用,避免造成内存浪费(比如不恰当的闭包使用会导致内存泄漏,过多的全局变量等)
  • JavaScript大概回收流程
    • JavaScript会不定时的进行内存回收,每次回收过程会将无法访问的变量以及保存的数据占用 的内存进行释放。
    • 回收过程是无法预估的,同时速度会非常快。
    • JavaScript在进行每次回收操作时,都会阻碍程序的运行
  • JavaScript回收流程的触发时间
    • 不定时的,会受到数据的影响。如果你频繁的创建对象或数组等,那么会加大JavaScript回收程序的调用频率。
  • 如何确定一个变量是否可以访问
    • 函数调用过程中创建的局部变量,在函数调用后是不能访问的(闭包除外)
    • 手动将变量赋予null
  • 如何提高内存的使用率
    • 针对全局变量。
      1. 尽量在程序的开头就先定义好全局变量,如果有全局变量是程序执行中间才有数据的话,可以初始化为null
      2. 当如果有一个全局变量不再使用,那么手动赋予null。
    • 针对程序中创建并使用的对象
      • 尽量复用创建的对象。(比如一般在复杂的动画中,一般会定义一个数组,里面保存了多个待使用的对象,在程序中就直接使用数组中的对象,就不再额外的创建新的对象)。主要目的是减少回收程序的频繁调用。