《javascript高级程序设计》笔记:内存与执行环境

苗疆三刀的随手记 2019-06-26

上一篇:《javascript高级程序设计》笔记:继承
近几篇博客都会围绕着图中的知识点展开

《javascript高级程序设计》笔记:内存与执行环境

由于javascript是一门具有自动垃圾收集机制的编程语言,开发者不必担心内存的分配和回收的问题。因此,内存一词在javascript编程中被开发者提及较少,更有一些非专业计算机相关专业出身的开发人员对javascript中内存的概念全无,但这丝毫不影响内存在编程中的重要程度

1. 堆内存/栈内存

1、存放变量的比较

栈内存用于存放基本类型、引用类型的地址和程序的执行(占用内存已知)
堆内存用于存放引用类型的真实内容,用于存放对象和函数(占用内存未知)

2、存取方式的比较

栈内存:“先进后出,后进先出”——类比兵兵球盒,仅当上面的出栈才能执行下面的

《javascript高级程序设计》笔记:内存与执行环境

堆内存:“随意存取”——类比书橱,不受入栈出栈的影响,需要某个对象或方法时,使用指针引用即可

3、内存为什么区分堆和栈(重点)

内存占用大小一定程度上决定了程序执行的流畅程度,内存区分堆和栈就是从内存管理机制上使程序运行时占用的内存最小(这与垃圾回收机制有关,后续介绍)

当一个方法执行时,每个方法都会建立自己的内存栈(执行环境),在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;

当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它

4、基本类型与引用类型(内存分析)

在博客《javascript高级程序设计》笔记:值类型与引用类型中有详细讲解

5、垃圾回收

javascript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存

不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)

好比一个餐厅,盘子总是有限的,所以服务员会去巡台回收空盘子
(1)自动回收:标记清除会将空盘和装菜的盘作上标识,当服务员巡台时,会收回空盘,释放内存
(2)手动回收:手动倒掉了盘子里面的菜(=null),在下次巡台时那盘子就会被收走了
(3)内存泄露:装着菜的盘子巡台时无法回收,但没有到客人桌上

2. 执行环境

执行环境(execution context)也被称为执行上下文,它是javascript中最为重要的一个概念

执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为

每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中(包括arguments/函数/变量)

每次当控制器转到可执行代码(全局或执行函数)的时候,就会进入一个执行上下文。执行环境创建时,变量对象、作用域链和this指向确定(和面章节会介绍)

执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。JavaScript中的运行环境大概包括三种情况:
(1)全局环境:JavaScript代码运行起来会首先进入该环境
(2)函数环境:当函数被调用执行时,会进入当前函数中执行代码
(3)eval

因此在一个JavaScript程序中,必定会产生多个执行上下文。栈底永远都是全局上下文,而栈顶就是当前正在执行的上下文

下面结合代码和图解分析:

var color = 'blue';

function changeColor() {
  var anotherColor = 'red';

  function swapColors() {
    var tempColor = anotherColor;
    anotherColor = color;
    color = tempColor;
  }

  swapColors();
}

changeColor();

步骤:
(1)全局上下文入栈
(2)碰到changeColor()后,changeColor的执行上下文入栈
(3)碰到swapColors()后,swapColors的执行上下文入栈
(4)swapColors()执行完毕,swapColors的上下文从栈中出栈
(5)changeColor()执行完毕,changeColor的上下文从栈中出栈

图解:

《javascript高级程序设计》笔记:内存与执行环境

调试图解:
(1)进入全局上下文(可以看到变量提升的效果)

《javascript高级程序设计》笔记:内存与执行环境

(2)进入changeColor执行环境

《javascript高级程序设计》笔记:内存与执行环境

(3)进入swapColors执行环境,图中形成了一个闭包closure,里面有变量anotherColor值

《javascript高级程序设计》笔记:内存与执行环境

(4)swapColors的执行环境出栈,回到changeColor执行环境,闭包消失

《javascript高级程序设计》笔记:内存与执行环境

(5)changeColor的执行环境出栈,回到全局环境

《javascript高级程序设计》笔记:内存与执行环境

总结:
(1)全局执行环境在js代码开始执行时就创建了,在浏览器关闭时出栈
(2)每次某个函数被调用,就会有个新的执行上下文为其创建,即使是调用的自身函数,也是如此
(3)函数的执行上下文的个数没有限制
(4)同步执行,只有栈顶的上下文处于执行中,其他上下文需要等待

下一篇:《javascript高级程序设计》笔记:变量对象与预解析
经典推荐:《javascript高级程序设计》笔记:原型图解

相关推荐