预解析
在当前作用域下,js运行之前,会把带有var和function关键字的事先声明,并在内存中安排好。 然后再从上到下执行js语句。 预解析只会发生在通过var定义的变量和function上。
步骤
- 先找var、function关键字以及参数
- 如果找到了var(声明的变量,参数),会赋给它一个undefined。如果找到function,那它会把整个函数都拿过来。
- 把找到的东西,放到作用域最开始的位置
- 逐行执行代码
<script>
console.log(a); //undefined
var a=10;
console.log(a); //10
var b=12;
function fn(){
console.log(b); //undefined
var b=20;
}
fn();
</script>
预解析题目练习
<script>
var c=10;
function fn1(){
console.log(c); //10
c=20;
}
fn1();
console.log(c); //20
</script>
var d=12;
function fn2(d){
console.log(d); //undefined
d=24;
}
fn2();
console.log(d); //12
var e=13;
function fn3(e){
console.log(e);//13
e=54;
}
fn3(e);
console.log(e);//13
函数预解析
函数
- 函数声明
函数声明可以被预解析,所以可以先调用再声明
- 函数表达式
函数表达式不会被预解析,所以只能先声明再调用,不能把调用放在声明的前面(否则报错)
<script>
fn1();
function fn1(){
console.log('fn1');
}
fn2(); //error
var fn2=function(){
console.log('fn2');
}
fn2();//fn2()
</script>
闭包
函数嵌套函数,子函数可以访问父函数的变量,就产生了一个闭包环境
<script>
function fn1(){
var n=10; //局部变量
function fn2(){ //局部函数
n++;
console.log(n);
}
fn2(); //11
}
fn1();//11
fn1();//11
console.log(n); //error
fn2(); //error
</script>
声明周期
变量或者函数在相应的作用域里存在的时间
局部变量
不用使用了,就是生命周期的结束。局部变量是在函数内声明的,当函数执行完成以后,这个变量就不存在了。
全局变量
声明完成之后,在整个页面都可以用,当页面关闭的时候,它的生命周期就结束了
垃圾回收机制
变量存在内存当中,变量在使用完以后,没有在其它的地方再使用,就会被清除,用来释放内存。垃圾回收机制会按照固定的时间,周期性的执行
<script>
function fn1(){
var b=12;
}
fn1();
console.log(b);//error
</script>
变量b在函数fn1执行完成之后,发现在别的地方没有再使用,那它就会被垃圾回收机制所回收
<script>
function fn1(){
var b=12;
}
fn1();
console.log(b);//error
function fn2(){
var n=10;
function fn3(){
n++;
console.log(n);
}
fn3();
}
fn2(); //11
fn2(); //11
</script>
最后,fn2函数在执行完成以后,变量n在其他地方没有被使用,所以n在fn2执行完成以后,发现在别的地方没有再使用,所以n在fn2执行完成以后会被垃圾回收机制所回收。再去设fn2的时候,此时内存当中已经没有n这个变量了,只不过重新声明了一个n。