预编译这个是js中无法避免的一个知识点,其涉及到AO(局部变量)和BO(全局变量)
前面在聊var的时候,说过var会提升,再看一下
变量提升
function test(){
console.log("=======",a);
var a;
}
可以看出声明变量是什么时候赋值的?
function test(){
console.log("=======",a);
var a=2;
console.log("=======",a);
}
可以看出变量首先在作用域会提升,赋值undefined,然后变量才会得到赋的值。
函数提升
其实这个涉及到预编译了,现在再添加一行新命令。
function test(){
console.log("=======",a);
function a(){"可以方法体内逻辑"}
}
这个地方也可以看出方法也是提升了。
如果是字面量写方法呢?
function test(){
console.log("=======",a);
var a =function (){"可以方法体内逻辑"}
}
可以可以看出字面量写函数,就相等于一个变量,不会将其作为函数进行提升。
预编译初了解
函数和变量提升的优先级
现在简单了解了函数中变量和函数提升,那涉及到一个问题,变量提升和函数提升,那个优先?
function test(){
console.log("=======",a);
function a(){"可以方法体内逻辑"}
var a;
}
在作用域中,不管变量和函数写在什么位置,所有变量会被整体提升到作用域顶部,所有函数也会被整体提升到作用域顶部,但是函数整体在变量整体的后面。
作用域包括全局作用域、函数作用域(闭包形成的作用域也是个函数作用域),总之都是在作用域中声明变量和函数时,会提升到作用域顶部。
为什么用方法来显示,是因为方便演示效果而已,所以不要老是觉得作用域只是函数作用域。
上面演示在方法中,调用的方法都是无参的,如果调用带有参数的呢?
#证明函数可以正常运行
function test(a){
console.log("=======",a);
var a=1;
console.log("=======",a);
}
#调用
test(2)
function test(a){
console.log("=======",a);
var a=1;
console.log("=======",a);
function a(){}
console.log("=======",a);
}
#调用
test(2)
神奇不?
具体的执行过程是:
#第一步 全局预编译函数test方法。
#第二步:test(2)调用了这个方法:
1:a变量定义 ----> undefined ---> 2
2: 预编译的时候看见发现有方法a 所以变量a ---> function a(){} 覆盖了a=2
3: 然后 a——————> 1
现在再看一道题,先不看结果,自己先搞以
a=1;
function test (b){
console.log(b);
function b(){}
arguments[0]=2;
console.log(b);
if(a){
var c=3;
}
var d;
a=4;
var a;
e=5
console.log(d);
console.log(a);
}
var a;
test(1)
console.log(a);
console.log(e);
arr=[]
for(var i=0;i<4;i++){
arr.push(i)
}
然后看下面截图:
了解了预编译的过程,就有了聊AO和BO的一些基础,下篇聊。