重学javaScript (四)| 执行上下文栈和变量提升

155 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

前言

上一节简单了解了js的v8引擎,那么大家好奇js代码是怎样在v8引擎里运行的吗?下边我们来解析下全过程

第一步代码被解析

先来简单的回顾下上一章说到的一个流程图

f23d5202ec9645b8b249e5e180926231~tplv-k3u1fbpfcp-zoom-in-crop-mark-1304-0-0-0.image.png

大概是这么个过程,那么当你写下一行js代码的时候它是怎么运行的呢?

我们来举个例子,先来看一段简单的代码

var name = 'juejin'
var age = '77'
var school = 'juejin'

上述代码定义了三个简单的变量,这个时候我们的js引擎做了如下的几件事 当代码被解析的时候,v8引擎会帮我们创建一个 GlobalObject对象,也就是上图javascript源码到parse这一步,也就是代码的解析阶段,这个GlobalObject对象会包含js中最初始的一些类,例如date,string,Math,settimeout等,正是有了GlobalObject对象我们才能直接使用上述全局的一些类,这个GlobalObject对象不仅仅是创建了一些常用的类,还创建了一个window的属性,指向了自己. 来看下下面的伪代码就全明白了.

  var GlobalObject = {
          String:'类'Date:'类',
          settimeout:'函数',
          window:GlobalObject
  }

因为是在解析代码,所以这个v8引擎会把我们定义的变量也放到了这个 GlobalObject的变量中,因为此时代码还没有被执行,所以此时它们的值还都是undefined ,因为只有执行的时候才会给它赋值,在解析阶段只是知道你有这么个属性

   var GlobalObject = {
          String:'类',
          Date:'类',
          settimeout:'函数',
          window:GlobalObject,
          name:undefined,
          age:undefined,
          school:undefined
          
  }

这个 GlobalObject 还有个名字就叫GO,以后我们都这么叫它

第二步,代码的运行

  1. v8引擎为了执行我们的代码,它内部会有一个执行上下文栈也就是函数调用栈,英文名称Execution Context Stack, 简称ECStack。所有代码的执行都需要放到这个栈里,一般是放入的函数

截屏2022-06-03 23.29.50.png

  1. 因为我们执行的是全局代码,为了全局代码能够正常执行,需要创建一个全局执行上下文(Global Execution Context),它只会在全局代码需要执行的时候,才会被创建,然后放入我们的执行上下文(ECStack),这个全局执行上下文中还有创建一个叫VO (variable object)的对象,它指向的其实就是之前创建的GO

image.png

  1. 接下来才是真正的执行代码,当代码遇到name变量时,从vo里找这个变量,因为vo指向go,也就是从go里找,这个时候会把3. 接下来才是真正的执行代码,当代码遇到name变量时,从vo里找这个变量,因为vo指向go,也就是从go里找,这个时候会把go里的name由undefined改为juejin,后续的变量也是一样的道理。

image.png

变量提升

这个时候,如果我们在代码的最后一行打印一个console.log(name),它就会去我们的vo里找name,这个时候自然而然的是juejin

var name = 'juejin'
var age = '77'
var school = 'juejin'

console.log(name)

代码执行结果如下

image.png

如果我们这时候在代码的第二行打印一下age呢,它会打印什么呢,因为在go中存在这个变量,因为给它赋值的代码还没有被执行,因此它的值这个时候是undefined,而不会报错说找不到这个变量,这个就是常说的变量提升,也叫作用域提升

var name = 'juejin'
console.log(age)
var age = '77'
var school = 'juejin'
console.log(name)

代码执行结果如下

image.png