360   JS

一,闭包用途:

 

1,因为JS的变量具有不同的作用域,当外部想访问函数内部的局部变量时,需要通过闭包来实现;

2,闭包的另外一个好处是,让函数内部的变量保持在内存中,便于下次访问;

 

二,测试闭包
1,简单闭包使用

var addNum;
function foo(){
        // 函数局部变量
        var num= 1;
	
        // 全局方法
 	addNum = function(){
		num = num+1;
                console.log('addNum:'+num); 
	}   
	
        // 闭包函数
	var getNum = function(){
		console.log('getNum:'+num); 
		return num;
	};
	
        // 返回闭包
	return getNum;
	 
};
// 获取闭包
var test = foo();
// 调用闭包,从而获得函数内部局部变量num的值
console.log(test()); 
// 调用全局方法,使函数内部局部变量num自加1,证明num=1是否仍在内存
addNum();
// 调用闭包,从而获得函数内部局部变量num的值
console.log(test()); 

 

测试结果:

 

getNum:1
1
addNum:1
getNum:2
2

 

2,循环调用闭包

function foo(){
	var getNum=[];
	for(i=0;i<3;i++){
		// 闭包函数数组
		getNum[i]=function(){
			console.log('getNum:'+i); 
			return i;
		}
	}
	// 返回闭包函数数组
	return getNum;
	 
};
// 获取闭包函数数组
var test = foo();
// 调用闭包函数
console.log(test[0]()); 
console.log(test[1]()); 
console.log(test[2]()); 

预测会显示:0,1,2
结果被打脸了,显示全部为3

getNum:3
3
getNum:3
3
getNum:3
3

 

为啥会这样了,这是因为调用闭包函数去获取函数局部变量num时,只是获得num的变量引用,而这个引用最后指向了3;

解决方法:使用立即调用函数,在赋值闭包函数给getNumb时就立即调用,获得当前引用值,同时在本地保存这些引用值,再传递给闭包函数

 

 

修改后的代码

 

function foo(){
	var getNum=[];
	for(i=0;i<3;i++){
		// 闭包函数数组,利用立即调用函数
		getNum[i]=(function(i){
			console.log('getLocalNum:'+i); 
               
			var getLocalNum = function(){
				return i;
			}
			return getLocalNum;
		})(i)
	}
	// 返回闭包函数数组
	return getNum;
	 
};
// 获取闭包函数数组
var test = foo();
// 调用闭包函数
console.log('getNum'); 
console.log(test[0]()); 
console.log(test[1]()); 
console.log(test[2]()); 
 

 

 

显示的结果也说明了,立即调用函数在闭包赋值的时候就执行了

getLocalNum:0
getLocalNum:1
getLocalNum:2
getNum
0
1
2

 

三,注意事项:

1,正因为闭包把函数局部变量保留在内存,要注意内存泄露,或者爆满,不使用的变量记得注销掉;
2,闭包不仅可以访问函数局部变量,还能修改变量值,如果你不想在外部修改函数内部的变量,就得注意了;




Leave a Reply

Your email address will not be published. Required fields are marked *