javaScript-执行上下文与执行上下文栈

2021-05-28·5min
type
Post
summary
status
Published
category
tags
slug
date
May 28, 2021
password
icon

执行上下文

执行上下文,简单理解就是代码执行的环境。
在JS中,有三种执行上下文,分别是全局执行上下文、函数执行上下文,eval执行上下文(不作了解)。
首先要理解的是,JS的代码不是一行一行执行,而是一段一段的执行。每段也就是一个执行上下文。
每个上下文在开始执行前,都会做一个准备工作,这个工作有三个重要的属性,分别是:变量对象,作用域链,以及this。

变量对象

变量对象是与执行上下文相关的数据作用域,保存了上下文中所有以var关键字声明的变量以及函数声明。
由于全局上下文与函数上下文中的变量对象不尽相同,所以下面分类讨论。

全局变量对象

首先下结论,全局中的变量对象就是全局对象。
在客户端javaScript中,这个全局对象就是window。
全局对象是一个预定义的对象,保存了一堆预定义的属性和方法。
所有在全局上下文中以var关键字声明的变量以及函数声明都会保存在全局对象中。
全局对象是作用域链的顶层,

函数变量对象

在函数执行上下文中,用活动对象代指变量对象。
这两个其实是一个东西,区别是变量对象我们是不可以直接访问的。
当进入一个执行上下文后,变量对象被激活,转换为活动对象,其上的属性和方法,我们才可以进行访问。
函数执行上下文中的活动对象通过函数的Arguments对象进行初始化。

执行过程

执行上下文的代码分为两个阶段进行处理: 分析和执行,我们也可以叫做:
  1. 进入执行上下文
  1. 执行代码
下面分析这两个过程中变量对象的情况。

进入执行上下文

  1. 激活变量对象,通过Arguments对象初始化活动对象(如果是函数执行上下文)
      • 键名为形参,键值为对应的实参。
      • 如果没有对应的实参,键值为undefined。
  1. 上下文中所有函数声明
      • 所有函数声明都会加入变量对象。
      • 键名为函数名,键值为函数体。
      • 如果变量对象中有重名的键,对其进行覆盖。
  1. 上下文中所有以var关键字声明的变量
      • 所有以var关键字声明的变量都会加入变量对象。
      • 键名为变量名,键值为undefind。
      • 如果变量对象中有重名的键,什么都不做。
举个例子:
进入执行上下文时,活动对象的情况如下:

执行代码

在代码执行阶段,会顺序执行代码,变量对象会根据代码修改自己的值。
还是上面的例子,代码完毕,活动对象情况如下:
到此变量对象的整个创建过程就结束了,总结一下:
  1. 全局上下文中的变量对象就是全局对象。
  1. 函数执行上下文的初始化只包括Argumens对象。
  1. 在进入执行上下文时,变量对象会添加形参,函数声明,以及以var关键字声明的变量。
  1. 在代码执行阶段,变量对象会根据代码对值进行修改。

作用域链

当想获取一个属性或方法时,会首先从当前上下文的变量对象中查找,如果没有,再去父级上下文的变量对象中查找,一直找到全局的变量对象,也就是全局对象。如果还找不到,就会报错。
这样多个变量对象组成的链表,我们称之为作用域链。
下面以一个函数的创建和调用两个时期,描述作用域链是如何变化的。

函数创建

首先要知道的是,JS中采取的是词法作用域。
也就是说,在函数创建时,它所有的父级变量对象已经决定好了,这一点不会随着它调用的位置而发生改变。
在函数的内部,有个[[scope]]属性。在函数创建时,这个属性会保存所有父级变量对象组成的作用域。
注意:[[scope]]属性不代表完整的作用域链!
举个🌰 :
函数创建时,各自的[[scope]]为:

函数调用

函数调用,进入一个函数执行上下文,创建完变量对象后,会将变量对象添加到作用域链的前端。
至此,作用域链创建完毕。

this

执行上下文栈

在我们写的代码中,会有不止一个函数,也就是说,会有很多个函数执行上下文被创建和执行。
为了统一管理执行上下文, JavaScript 引擎会创建一个执行上下文栈来统一进行管理。
执行上下文栈是一种先入后出的结构,下面简单阐述一下它的运行情况。
  1. 当JS解释器开始执行代码时,最先遇到的就是全局代码,所以会先向执行上下文栈中压入一个全局执行上下文。这个全局执行上下文只有在整个应用程序结束,或者页面被关闭时,才会被弹出栈。
  1. 当一个函数被调用时,就会创建一个函数执行上下文,并把它压入栈中。当函数执行结束,再把它弹出栈。

参考链接

JavaScript深入之词法作用域和动态作用域

JavaScript深入之执行上下文栈

JavaScript深入之变量对象

JavaScript深入之作用域链

JavaScript深入之执行上下文

> cd ..