浅谈JavaScript执行机制

218 阅读4分钟

一、前言


在现代网页开发中,JavaScript作为一种高效且灵活的编程语言,扮演着不可或缺的角色。它不仅赋予了网页动态交互的能力,还在后端开发中得到了广泛应用。然而,了解JavaScript的执行机制对于开发者而言至关重要,因为它直接影响到代码的性能和行为。

首先我们先来看一段代码

showName()
console.log(myname)

var myname = 'zhangsan'
function showName() {
  console.log('函数showName被执行')
}

在v8引擎眼中代码是长这个样子的

var myname
function showName() {
  console.log('函数showName被执行')
}
showName()
console.log(myname)
myname = 'zhangsan'

这就是大家所熟知的声明提升,但是为什么会出现声明提升呢?那接下来我们就不得不聊聊js的执行机制了。

二、js的执行机制介绍

image.png 即一段js代码交给v8引擎,它会先读取它,然后对他进行预编译,编译完之后才会执行

v8引擎一读取到这段代码就会创建执行上下文对象并放入调用栈中,然后再执行。 一个执行上下文由三部分组成:变量环境 词法环境还有可执行代码

image.png 变量环境:主要用来储存var定义的变量和函数的声明

词法环境:主要用来储存let和const定义的变量和函数的词法作用域信息

调用栈:v8 引擎用来管理函数之间的调用关系的一种结构

1.编译总是发生在执行前一刻

2.全局和函数体的编译会生成执行上下文,存入调用栈

3.当一个函数执行完毕后,他的执行上下文就会被销毁

编译的过程

1.创建执行上下文对象

2.找形参和变量声明,将形参和声明的变量名作为key,值为undefined

3.统一形参和实参的值 (全局没有该步骤)

4.找函数声明,将函数名作为key,值为函数体

三、实践巩固

以上内容我们就拿一段代码来举例

var a = 1
function fn(a) {
  var a = 2
  function a() { }
  var b = a
  console.log(a)
}
fn(3)

先是创建全局执行上下文,读取到 var = 1,有变量声明,将 a = undefined 放进变量环境中,由于全局上下文没有第三步统一形参实参的值,此找到函数声明 fn 全局执行上下文编译完成

image.png 编译完成后开始执行

将 1 赋值给变量 a,调用函数 fn 并传入实参 3,在调用函数时会创建函数 fn 执行上下文 image.png

同样开始编译,找到函数中形参a ,将 a = undefined 放入变量环境,同样看见 var a = 2, 将 a = undefined覆盖第一次的a,看到var b = a ,将 b = undefined放入变量环境中至此第二步已经完成了,接下来统一形参实参值,将 实参 3 赋值给 a , 随后进行第四步找函数声明,找到了声明了一个函数 a ,那么此时 a = function(){}, fn 执行上下文编译环节结束。进入执行阶段, 将 2 赋值给 a,此时 a = 2 ,注意此时第四行的 function a (){} 是声明一个函数,在执行阶段我们可以无视它, 将 a 的值赋值给 b , 此时b = 2 ,随后打印出 a 的值,此时 a 的值是 2,即输出 2 。

image.png

四、总结

执行上下文

1.代码先编译再执行

js 执行流程

1.读取代码 2.编译 3.执行

调用栈

v8 引擎用来管理函数之间的调用关系的一种结构

1.编译总是发生在执行前一刻

2.全局和函数体的编译会生成执行上下文,存入调用栈

3.当一个函数执行完毕后,他的执行上下文就会被销毁

编译的过程

1.创建执行上下文对象

2.找形参和变量声明,将形参和声明的变量名作为key,值为undefined

3.统一形参和实参的值 (全局没有该步骤)

4.找函数声明,将函数名作为key,值为函数体