关于JavaScript代码执行的两个阶段

2022-03-26  本文已影响0人  默默无闻的小人物

执行JavaScript代码主要分为以下两个阶段

注意预编译过程中的3点会帮助我们正确理解和判断代码逻辑。看如下题目:

function bar(){
    console.log('bar1')
}
var bar =function(){
    console.log('bar2')
}
bar()
// 输出bar2

调换一下代码顺序

var bar =function(){
    console.log('bar2')
}
function bar(){
    console.log('bar1')
}
bar()
// 输出bar2

以上代码输出的结果都是bar2,因为在预编译阶段虽然对变量进行了声明和提升,但是不会对其进行赋值。函数bar被创建并且提升。但是在代码执行阶段的时候才会(通过表达式)赋值。

可以把上面代码理解为以下代码

function bar(){
    console.log('bar1')
}
var bar = undefined;
bar = function () {
     console.log('bar2')
}
bar()

这样就能理解为啥都是输出bar2了吧。

请再思考一下以下这道题

foo(10)
function foo(num){
    console.log(foo)
    foo=num
    console.log(foo)
    var foo
}
console.log(foo)
foo=1
console.log(foo)

根据上面说的JavaScript预编译的3个注意点我们可以将代码转换成如下

function foo(num){
    var foo=undefined
    console.log(foo)
    foo=num
    console.log(foo)
}
foo(10)
console.log(foo)
foo=1
console.log(foo)

这样就能知道以上输出分别是什么

undefined
10
foo函数本身
1

结语:

作用域在预编译阶段确定,但是作用域链是在执行上下文的创建阶段完全生成的,因为函数在调用时才会创建对应的执行上下文。执行上下文包裹变量对象、作用域链以及this的指向

代码执行的整个过程说起来就像一条生产流水线。第一道工序是在预编译阶段创建变量对象(Variable Object,VO),此时只是创建,未进行赋值。到了下一道工序代码执行阶段。变量对象会转为激活对象(Active Object,AO),即完成了VO向AO的转换。此时,作用域链也将被确定,它由当前执行环境的变量对象和所有外层已经完成的激活对象组成。这道工序保证了变量和函数的有序访问,即如果未在当前作用域找到变量,则会继续向上查找知道全局作用域。、

上一篇下一篇

猜你喜欢

热点阅读