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