先说下预解析的含义,在写js代码调用函数的时候,无论你是在调用位置的前面或者后面声明函数,都可以正常调用,原因是,JavaScript碰到script标签,会将var变量(注意是var)声明和函数声明(注意是声明)提升到当前作用域最前面。
要想搞懂预解析,先记住结论:
变量的提升,指的是声明的提升,赋值(初始化)并不会提升
接下来 就对着这个结论看一些例子:
例1:
console.log(num); //undefined
var num = 2;
变量声明提升,赋值不提升,所以上述代码相当于:
var num;
console.log(num);
num = 2;
例2:
var num = 2;
var num;
console.log(num); //2
是不是以为是undefined呢?千万别忘了变量是会提升的,看下面代码就明白为什么是2了:
var num;
var num;
num = 2;
console.log(num);
这里有个问题,看下面代码:
function f() {}
var f
console.log(f); //function f() {}
按理说,这里应该是undefined,结果明显不是,这里个人以为可以理解成,变量的声明提升后会在函数前面
再将代码作如下修改:
function f() {
console.log(num); // undefined
}
var num
这里函数里面能访问到num,证明变量的声明会在函数声明之前
这个问题是个人的理解,有疑问的读者也可以去查些资料。
例3:
var f = function() {
console.log(1)
}
function f() {
console.log(2)
}
f(); // 1
这个例子结果是1的原因,可以看下面的代码:
var f;
function f() {
console.log(2)
}
f = function() {
console.log(1)
}
f();
例4:
f(); // 2
var f = function() {
console.log(1)
}
function f() {
console.log(2)
}
这个例子和前一个只是函数调用位置发生了改变,结果也变了,可以尝试自己按照步骤一步步重新写在纸上,结果如下:
var f;
function f() {
console.log(2)
}
f();
f = function() {
console.log(1)
}
例5:
f(); //报错
var f = function(){
console.log('k')
}
这个例子应该很简单,只是将例1中的变量换成了函数:
var f;
f();
f = function(){
console.log('k')
}
调用一个未赋值的函数,当然会报错,注意一下,这个例子,将函数表达式换成函数声明就不会报错了,因为函数声明会提升,这也是我们常用函数声明的一个原因,可以在任何位置调用。
例6:
var num = 2;
function f() {
num = 1;
console.log(num); //1
return
var num = 3;
}
f();
console.log(num) //2
return后面的语句虽然不会执行,但是变量还是会提升:
var num = 2;
function f() {
var num
num = 1;
console.log(num); //1
return
num = 3;
}
f();
console.log(num) //2
例7:
console.log(num);// 报错
num = 2;
我们开篇就说过,只有var会提升,隐式全局变量并不会提升,所以结果和例1不同,并不是undefined