一、前言
在现代网页开发中,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的执行机制介绍
即一段js代码交给v8引擎,它会先读取它,然后对他进行预编译,编译完之后才会执行
v8引擎一读取到这段代码就会创建执行上下文对象并放入调用栈中,然后再执行。 一个执行上下文由三部分组成:变量环境 词法环境还有可执行代码。
变量环境:主要用来储存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 全局执行上下文编译完成
将 1 赋值给变量 a,调用函数 fn 并传入实参 3,在调用函数时会创建函数 fn 执行上下文
同样开始编译,找到函数中形参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 。
四、总结
执行上下文
1.代码先编译再执行
js 执行流程
1.读取代码 2.编译 3.执行
调用栈
v8 引擎用来管理函数之间的调用关系的一种结构
1.编译总是发生在执行前一刻
2.全局和函数体的编译会生成执行上下文,存入调用栈
3.当一个函数执行完毕后,他的执行上下文就会被销毁
编译的过程
1.创建执行上下文对象
2.找形参和变量声明,将形参和声明的变量名作为key,值为undefined
3.统一形参和实参的值 (全局没有该步骤)
4.找函数声明,将函数名作为key,值为函数体