回收机制
一个变量或函数执行完后,下面的代码没有在使用或调用时会被回收回去,释放出内存。定义一个变量、函数会在内存占一定的空间;(全局变量、函数不会被回收)
了解函数调用
<script>
var num = 0 ;
function a(){
num = 10;
console.log(num);
}
function b(){
num = 20;
a();
}
b();
执行顺序:
看全局:
1、定义
var num
函数a
函数b
2、执行代码
num = 0
b(); == 新的作用域
1、定义没有
2、执行代码
num = 20
a(); == 新的作用域
1、定义没有
2、执行代码
num = 10;
console.log(num); ===>打印 10;
上面嵌套就是函数调用
function a(){
var num = 10;
function b(){ //这层下可以访问 num
num ++;
console.log( num );
}
return b;
}
a();
b层可以访问到num 我们可以把 b return上去
</script>
一、
fn();
function fn(){
var a = 10;
alert( a ); ===>a没有再被引用,会被回收
} (在下面的代码毫无作用的时候)
二、
fn();
function fn(){
var oBox = document.getElementById( 'box' );
oBox.onclick = function (){
var a = oBox.id; 这里的oBox 不会被回收
}
}
oBox是事件函数,没办法确定用户什么时候会去点击,所以这里oBox.id会时时存在;
另一种写法
fn();
function fn(){
var oBox = document.getElementById( 'box' );
oBox.onclick = function (){
var a = this.id; 会被回收
}
}
this只有当事件触发时才会指向谁,在没有点击的时候不会有指向,所以会被回收;
前提是:后面没有oBox的应用;
什么是闭包
当一个函数里嵌套了一个函数
内部函数引用了外部函数的参数或者变量
那么这个参数/变量不会被回收,这样就形成一个闭包
var b = fn(); // b {var a = 20; return function (){ a ++; alert( a ); }}
b();// var a = 20; return function (){ a ++; alert( a ); } 弹出21
b();// a = 21; return function (){ a ++; alert( a ); } 弹出22
b();// a = 22; return function (){ a ++; alert( a ); } 弹出23
fn()(); fn()===> var a = 20; return function (){ a ++; alert( a ); }
fn()()再让上面的函数执行 function (){ a ++; alert( a ); 弹出 21
function fn(){ ===>嵌套
var a = 20; ==>不会被回收
return function (){
a ++;
alert( a ); 内部引用a
}
}
这里fn()()各b是不同的闭包,是2个闭包
闭包的应用
<div id='box'>
<p>0</p>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
</div>
var oBox = document.getElementById ( 'box' ),
aP = oBox.getElementsByTagName( 'p' ),
length = aP.length;
for( var i=0 ; i<length ; i++ ){
aP[i].i = i;
aP[i].onclick = function (){
alert( this.i ); //点击哪个弹出对应的序号;
}
}
之前用的方法
用闭包实现
for( var i=0 ; i<length ; i++ ){
function fn( x ){
// 相当于 var x ;
aP[x].onclick = function (){ //嵌套函数
alert( x ); //点击哪个弹出对应的序号; ===>调用上面的变量 x 不会被回收
}
}
fn(i); ==>传i进去
}
注意:这里产生了5个闭包
function fn(){
var x = 0 ;
aP[0].onclick = function (){ //嵌套函数
alert( 0 ); //点击哪个弹出对应的序号; ===>调用上面的变量 x 不会被回收
}
}
fn(0); ==>传i进去
function fn(){
var x = 1 ;
aP[0].onclick = function (){ //嵌套函数
alert(1 ); //点击哪个弹出对应的序号; ===>调用上面的变量 x 不会被回收
}
}
fn(1); ==>传i进去
...
一直到5
上面定义一个函数马上就执行,我们可以写成自执行的形式,可以减少一个变量名;
for( var i=0 ; i<length ; i++ ){
(function fn( x ){
aP[x].onclick = function (){ alert( x ); }
})(i);
}
应用二、
二、
<script>
function fn(a){
var b = 'hello';
return function (){
alert( a );
alert( b );
}
}
fn(2)//得到的是; function (){alert( a );alert( b );}
fn(2)()//再上面的函数执行 先弹2 再弹hello
也可以用变量存放起来;
var x= fn(20); ===>上面用了闭包 不会被回收
x();
在其他函数体里也可以调用
function run(){
x();
}
run()
</script>