初学JS,都会讲到变量提升这一概念
a = 10
var a;
console.log(a)
function foo() {}
var bar = function(){}
要想真正理解变量提升的来龙去脉,就得去理解 JS 代码得执行流程
以一段代码为例,让理解 JS 代码的完整执行流程
foo()
console.log(bar)
var bar = 'JS'
function foo(){
console.log('foo')
}
这样一段代码是怎样被浏览器的引擎来执行的?
编译阶段
而变量提升的原因,就在编译阶段,我们重点关注编译后的代码,以及整个代码的内存状况
上面这段代码经过编译后,会在内存中生成两个部分
- 执行上下文
执行上下文是JS执行代码的运行环境,类似操作系统中的上下文概念。它包括变量环境和词法环境。 而变量提升的奥秘主要就藏在变量环境之中。 变量提升后的内容被保存在了变量环境之中,使得可执行代码可以使用物理位置上还没声明的变量,JS引擎在编译阶段会检测代码中的变量,并将其保存在变量环境之中 - 可执行代码
在JS引擎将代码中的所有声明的变量保存在变量环境后,JS会将声明变量以外的代码编译为字节码,即可执行代码 下面就是上面这段代码编译后生成的可执行代码
foo()
console.log(bar)
bar='JS'
执行阶段
JS引擎开始执行可执行代码,按照顺序一行一行执行,像解释型语言一样。接下来我们一行一行分析可执行代码的执行流程
- foo() 函数调用,JS引擎会在变量环境中寻找foo函数,因为变量环境中存在foo函数的引用(因为JS对象都是存在堆区的),所以JS会调用该函数,打印 foo
- console.log(bar),同样JS引擎会在变量环境中寻找 bar 变量,因为变量环境中存在 bar,其值为默认值 undifined,所以打印输出 undifined
- bar=‘JS’,将 JS 赋值给 bar 变量,在赋值完成后,变量环境中的bar变量的值也会更新
以上就是JS代码的大概的执行流程
|