预解析
预解析:也叫变量提升,就是在当前作用域下,js运行之前,js的解释器会把带有var和function关键字的事先声明,并在内存中安排好。然后再从上到下执行js语句。
预解析只会发生在通过var定义的变量和function上。
通过var关键字定义的变量进行预解析的时候:只要是通过var定义的,不管是变量,还是函数,都是先赋值undefined,如果是变量,也不管变量有没有赋值,在预解析阶段,都是会被赋值为undefined。
<script>
console.log(a); //打印 undefined
var a = 1;
console.log(b); //打印 undefined
var b = function() {
console.log(c); //打印 undefined
};
b();
var c;
</script>
function进行预解析的时候,不仅是声明而且还定义了,但是它存储的数据的那个空间里面存储的是代码是字符串,没有任何意义。
<script>
console.log(a); //打印的是下面的function函数体
function a() {
console.log("预解析function");
}
</script>
预解析是发生在当前作用域下的,刚开始的时候,我们预解析的是全局作用域,在js中我们的global就是我们的window。 我们运行函数的时候会生成一个新的私有作用域(每次执行都是新的,执行完成就销毁)这个作用域下我们可以理解为开辟了一个新的内存空间。在这个内存中我们也要执行预解析。当我们的函数执行完成后,这个内存或者作用域就会销毁 如果在当前作用域下的一个变量没有预解析,就会向它的上一级去找,直到找到window,如果window下也没有定义,就会报错。所以,在函数内通过var定义的变量是局部变量,没有能过var 定义的变量是全局变量。 预解析不会在同一个变量上重复的发生,也就是一个变量如果已经在当前作用域下预解析了,不会再重复解析。
特别注意:在预解析的过程中,函数声明比变量声明优先
- 案例一
<script>
//函数声明在变量声明前面,所以打印的是函数a
console.log(a); //打印 a函数的函数体
var a = 10;
function a() {
var b = 20;
console.log(b);
}
</script>
//模拟预解析过程
//<script>
//变量和函数会提升,函数会优先于变量
//function a(){
//在函数内部也会进行预解析过程
//var b;
//b = 20;
//console.log(b);
}
//var a;
//-----------------------------------以上是js预解析的过程,此过程不会执行代码,只是在内存中开辟了相应的空间,并且会给变量a赋值为undefined,如果是定义的函数表达式,也会被赋值为undefined
//-------------------------js预解析过后,然后按照顺序执行代码
//console.log(a);
//a = 10;
//</script>
- 案例二
<script>
console.log(a); //打印a函数的函数体
console.log(a()); //打印结果为undefined
var a = 10;
function a() {
console.log(20); //打印20
}
console.log(a); //打印10
a = 50;
console.log(a()); //报错
</script>
//模拟预解析过程
<script>
//变量和函数会提升,函数会优先于变量
//function a(){
//console.log(20);
}
//var a;
//-----------------------------------以上是js预解析的过程,此过程不会执行代码,只是在内存中开辟了相应的空间,并且会给变量a赋值为undefined,如果是定义的函数表达式,也会被赋值为undefined
//-------------------------js预解析过后,然后按照顺序执行代码
//console.log(a);打印的是a函数的函数体
//console.log(a());首先会执行a函数,括号中是函数的调用,会打印20。由于a函数中没有返回值,函数会默认返回一个undefined,所以会打印undefined。
//a = 10;
//console.log(a); //此时a已经被赋值为10,所以打印的是10.
//a = 50;
//console.log(a()); //此时a已经被赋值为50,a已经不是函数了,再调用就会报错,也就不会被执行。就算a不被赋值为50,执行此行代码也会被报错,因为在前面a的值已经被赋值为10,就已经不是函数了。
</script>