你真的懂预编译和变量提升吗?

189 阅读2分钟

大家都知道,var定义数据时,会造成变量提升,但是为什么会造成变量提升呢?函数有变量提升吗?函数作用域内存在变量提升吗?如果答不上来,请耐心看完这篇文章,你不仅能解答上述的问题,同样也会了解js的预编译,相信你一定有不小的收获。

首先,js 运行时的三个过程:

1.语法分析:对代码通篇检查,排除一些低级错误
          
2.预编译:在代码执行前一刻
          
3.解释执行:执行代码

而变量提升,就是发生在预编译这个环节中的,预编译的四个步骤为:

1.创建AO对象

2.找出形参和变量声明,将变量声明的名作为AO对象的属性,值为undefined

3.将实参和形参相统一

4.找出函数声明(不是函数表达式),赋予其变量声明

这4个步骤是什么意思呢, 请看下面的代码:

function myTest(c, d) {
    console.log(c)
    c = 5;
    console.log(a);  
    var a = 1;
    var b = 2;
    console.log(b);  
    function a() { }
    console.log(c);  
    function c() { }
    console.log(c);  
}
myTest(2, 3)

请先预测一下上述打印结果

当执行上述代码时,预编译会有上面四个步骤:

1.创建AO对象

let AO = {
            
}

2.找出形参和变量声明,将变量声明的名作为AO对象的属性,值为undefined

let AO = {
    c: undefined 
    d: undefined 
    a: undefined   
    b: undefined
}

3.将实参和形参相统一

let AO = {
    c: undefined => 2
    d: undefined => 3
    a: undefined   
    b: undefined
}

4.找出函数声明(不是函数表达式),赋予其变量声明

let AO = {
    c: undefined => 2  =>function c() { }
    d: undefined => 3
    a: undefined       =>function a() { }
    b: undefined
}

预编译完了,此时c d a b 四个变量的值分别为 function c() { } ,3,function a() { },undefined ,不信我们可以打印一下:

function myTest(c, d) {
    console.log(c)   //ƒ c() { }
    console.log(d)   //3 
    console.log(a)   //f a(){}
    console.log(b)   //undefined
    c = 5;
    console.log(a);  //f a() { } 
    var a = 1;
    var b = 2;
    console.log(b);  //2
    function a() { }
    console.log(c);  //5
    function c() { }
    console.log(c);  //5
}
myTest(2, 3)

1678351796777.jpg

完全正确,好了,到现在已经可以很简单的回答上述的问题了,js预编译造成的变量提升,函数也有变量提升,函数内部存在变量提升。并且函数提升,是整体提升,包括函数内容,大家可以自己打印看一下哦。

再见!